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/pmt.h>
6 #include <lib/dvb/sec.h>
13 #include <sys/ioctl.h>
15 DEFINE_REF(eDVBRegisteredFrontend);
16 DEFINE_REF(eDVBRegisteredDemux);
18 DEFINE_REF(eDVBAllocatedFrontend);
20 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
25 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
30 DEFINE_REF(eDVBAllocatedDemux);
32 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
37 eDVBAllocatedDemux::~eDVBAllocatedDemux()
42 DEFINE_REF(eDVBResourceManager);
44 eDVBResourceManager *eDVBResourceManager::instance;
46 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
56 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
58 ePtr<eDVBResourceManager> ptr;
59 eDVBResourceManager::getInstance(ptr);
63 eDVBResourceManager::eDVBResourceManager()
64 :m_releaseCachedChannelTimer(eApp)
68 m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
72 /* search available adapters... */
77 while (eDVBAdapterLinux::exist(num_adapter))
79 addAdapter(new eDVBAdapterLinux(num_adapter));
83 eDebug("found %d adapter, %d frontends and %d demux",
84 m_adapter.size(), m_frontend.size(), m_demux.size());
86 eDVBCAService::registerChannelCallback(this);
88 CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
91 void eDVBResourceManager::feStateChanged()
94 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
96 mask |= ( 1 << i->m_frontend->getSlotID() );
97 /* emit */ frontendUseMaskChanged(mask);
100 DEFINE_REF(eDVBAdapterLinux);
101 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
106 eDebug("scanning for frontends..");
111 #if HAVE_DVB_API_VERSION < 3
112 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
114 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
116 if (stat(filename, &s))
118 ePtr<eDVBFrontend> fe;
121 fe = new eDVBFrontend(m_nr, num_fe, ok);
123 m_frontend.push_back(fe);
133 #if HAVE_DVB_API_VERSION < 3
134 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
136 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
138 if (stat(filename, &s))
140 ePtr<eDVBDemux> demux;
142 demux = new eDVBDemux(m_nr, num_demux);
143 m_demux.push_back(demux);
149 int eDVBAdapterLinux::getNumDemux()
151 return m_demux.size();
154 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
156 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
157 while (nr && (i != m_demux.end()))
163 if (i != m_demux.end())
171 int eDVBAdapterLinux::getNumFrontends()
173 return m_frontend.size();
176 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
178 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
179 while (nr && (i != m_frontend.end()))
185 if (i != m_frontend.end())
193 int eDVBAdapterLinux::exist(int nr)
197 #if HAVE_DVB_API_VERSION < 3
198 sprintf(filename, "/dev/dvb/card%d", nr);
200 sprintf(filename, "/dev/dvb/adapter%d", nr);
202 if (!stat(filename, &s))
207 eDVBResourceManager::~eDVBResourceManager()
209 if (instance == this)
213 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
215 int num_fe = adapter->getNumFrontends();
216 int num_demux = adapter->getNumDemux();
218 m_adapter.push_back(adapter);
221 for (i=0; i<num_demux; ++i)
223 ePtr<eDVBDemux> demux;
224 if (!adapter->getDemux(demux, i))
225 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
228 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
229 for (i=0; i<num_fe; ++i)
231 ePtr<eDVBFrontend> frontend;
232 if (!adapter->getFrontend(frontend, i))
235 frontend->getFrontendType(frontendType);
236 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
237 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
238 m_frontend.push_back(new_fe);
239 frontend->setSEC(m_sec);
240 // we must link all dvb-t frontends ( for active antenna voltage )
241 if (frontendType == iDVBFrontend::feTerrestrial)
243 if (prev_dvbt_frontend)
245 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (int)new_fe);
246 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (int)&(*prev_dvbt_frontend));
248 prev_dvbt_frontend = new_fe;
254 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
256 if (!PyList_Check(list))
258 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
261 if ((unsigned int)PyList_Size(list) != m_frontend.size())
264 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist",
265 m_frontend.size(), PyList_Size(list));
266 PyErr_SetString(PyExc_StandardError, blasel);
270 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
272 ePyObject obj = PyList_GET_ITEM(list, pos++);
273 if (!i->m_frontend->setSlotInfo(obj))
279 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
281 ePtr<eDVBRegisteredFrontend> best;
284 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
287 int c = i->m_frontend->isCompatibleWith(feparm);
297 fe = new eDVBAllocatedFrontend(best);
306 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
308 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
309 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
311 // check if another slot linked to this is in use
312 eDVBRegisteredFrontend *satpos_depends_to_fe =
313 (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR];
314 if ( (int)satpos_depends_to_fe != -1 )
316 if (satpos_depends_to_fe->m_inuse)
318 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
319 goto alloc_fe_by_id_not_possible;
322 else // check linked tuners
324 eDVBRegisteredFrontend *next =
325 (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
326 while ( (int)next != -1 )
330 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
331 goto alloc_fe_by_id_not_possible;
333 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
335 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)
336 i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
337 while ( (int)prev != -1 )
341 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
342 goto alloc_fe_by_id_not_possible;
344 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
347 fe = new eDVBAllocatedFrontend(i);
350 alloc_fe_by_id_not_possible:
355 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
357 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
358 never use the first one unless we need a decoding demux. */
360 eDebug("allocate demux");
361 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
363 if (i == m_demux.end())
367 /* FIXME: hardware demux policy */
368 if (!(cap & iDVBChannel::capDecode))
370 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
377 for (; i != m_demux.end(); ++i, ++n)
379 int is_decode = n < 2;
381 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
383 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
385 if ((cap & iDVBChannel::capDecode) && !is_decode)
388 demux = new eDVBAllocatedDemux(i);
390 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
392 demux->get().setSourcePVR(0);
396 eDebug("demux not found");
400 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
406 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
415 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
417 /* first, check if a channel is already existing. */
419 if (m_cached_channel)
421 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
422 if(channelid==cache_chan->getChannelID())
424 eDebug("use cached_channel");
425 channel = m_cached_channel;
428 m_cached_channel_state_changed_conn.disconnect();
430 m_releaseCachedChannelTimer.stop();
433 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
434 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
436 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
437 if (i->m_channel_id == channelid)
439 // eDebug("found shared channel..");
440 channel = i->m_channel;
445 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
449 eDebug("no channel list set!");
453 ePtr<iDVBFrontendParameters> feparm;
454 if (m_list->getChannelFrontendData(channelid, feparm))
456 eDebug("channel not found!");
460 /* allocate a frontend. */
462 ePtr<eDVBAllocatedFrontend> fe;
464 if (allocateFrontend(fe, feparm))
465 return errNoFrontend;
468 ePtr<eDVBChannel> ch;
469 ch = new eDVBChannel(this, fe);
471 res = ch->setChannel(channelid, feparm);
475 return errChidNotFound;
477 m_cached_channel = channel = ch;
478 m_cached_channel_state_changed_conn =
479 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
484 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
487 chan->getState(state);
490 case iDVBChannel::state_release:
491 case iDVBChannel::state_ok:
493 eDebug("stop release channel timer");
494 m_releaseCachedChannelTimer.stop();
497 case iDVBChannel::state_last_instance:
499 eDebug("start release channel timer");
500 m_releaseCachedChannelTimer.start(3000, true);
503 default: // ignore all other events
508 void eDVBResourceManager::releaseCachedChannel()
510 eDebug("release cached channel (timer timeout)");
514 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
516 ePtr<eDVBAllocatedFrontend> fe;
518 if (m_cached_channel)
520 m_cached_channel_state_changed_conn.disconnect();
522 m_releaseCachedChannelTimer.stop();
525 if (allocateFrontendByIndex(fe, slot_index))
526 return errNoFrontend;
529 ch = new eDVBChannel(this, fe);
536 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
538 ePtr<eDVBAllocatedDemux> demux;
540 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
542 m_cached_channel_state_changed_conn.disconnect();
544 m_releaseCachedChannelTimer.stop();
548 ch = new eDVBChannel(this, 0);
554 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
556 m_active_channels.push_back(active_channel(chid, ch));
557 /* emit */ m_channelAdded(ch);
561 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
564 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
566 if (i->m_channel == ch)
568 i = m_active_channels.erase(i);
579 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
581 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
585 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
587 ePtr<eDVBRegisteredFrontend> best;
590 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
593 int c = i->m_frontend->isCompatibleWith(feparm);
600 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
604 ePtr<iDVBFrontendParameters> feparm;
605 if (!channellist->getChannelFrontendData(chid, feparm))
608 if (!feparm->getSystem(system))
612 case iDVBFrontend::feSatellite:
614 case iDVBFrontend::feCable:
616 case iDVBFrontend::feTerrestrial:
627 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
630 if (m_cached_channel)
632 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
633 if(channelid==cache_chan->getChannelID())
634 return tuner_type_channel_default(m_list, channelid);
637 /* first, check if a channel is already existing. */
638 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
639 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
641 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
642 if (i->m_channel_id == channelid)
644 // eDebug("found shared channel..");
645 return tuner_type_channel_default(m_list, channelid);
649 int *decremented_cached_channel_fe_usecount=NULL,
650 *decremented_fe_usecount=NULL;
652 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
654 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
655 if (i->m_channel_id == ignore)
657 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
658 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
659 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
660 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
661 // or 2 when the cached channel is not equal to the compared channel
662 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
664 ePtr<iDVBFrontend> fe;
665 if (!i->m_channel->getFrontend(fe))
667 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
669 if ( &(*fe) == &(*ii->m_frontend) )
672 decremented_fe_usecount = &ii->m_inuse;
673 if (channel == &(*m_cached_channel))
674 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
684 if (!decremented_cached_channel_fe_usecount)
686 if (m_cached_channel)
688 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
689 if (channel->getUseCount() == 1)
691 ePtr<iDVBFrontend> fe;
692 if (!channel->getFrontend(fe))
694 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
696 if ( &(*fe) == &(*ii->m_frontend) )
699 decremented_cached_channel_fe_usecount = &ii->m_inuse;
708 decremented_cached_channel_fe_usecount=NULL;
710 ePtr<iDVBFrontendParameters> feparm;
714 eDebug("no channel list set!");
718 if (m_list->getChannelFrontendData(channelid, feparm))
720 eDebug("channel not found!");
724 ret = canAllocateFrontend(feparm);
727 if (decremented_fe_usecount)
728 ++(*decremented_fe_usecount);
729 if (decremented_cached_channel_fe_usecount)
730 ++(*decremented_cached_channel_fe_usecount);
735 class eDVBChannelFilePush: public eFilePushThread
738 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
740 int m_iframe_search, m_iframe_state, m_pid;
741 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
744 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
747 if (!m_iframe_search)
750 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
752 eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
754 unsigned char *d = data;
755 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
757 int offset = d - data;
758 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
759 unsigned char *ts = data + ts_offset;
760 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
762 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
764 int picture_type = (d[5] >> 3) & 7;
767 eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
769 if (m_iframe_state == 1)
771 /* we are allowing data, and stop allowing data on the next frame.
772 we now found a frame. so stop here. */
773 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
774 current_span_remaining = 0;
776 unsigned char *fts = ts + 188;
777 while (fts < (data + len))
780 fts[2] |= 0xff; /* drop packet */
784 return len; // ts_offset + 188; /* deliver this packet, but not more. */
787 if (picture_type != 1) /* we are only interested in I frames */
790 unsigned char *fts = data;
794 fts[2] |= 0xff; /* drop packet */
798 /* force payload only */
802 // memset(ts + 4, 0xFF, (offset % 188) - 4);
806 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
810 eDebug("now locked to pid %04x", pid);
820 if (m_iframe_state == 1)
823 return 0; /* we need find an iframe first */
829 DEFINE_REF(eDVBChannel);
831 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
833 m_frontend = frontend;
837 m_skipmode_n = m_skipmode_m = 0;
840 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
843 eDVBChannel::~eDVBChannel()
846 m_mgr->removeChannel(this);
851 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
853 int state, ourstate = 0;
855 /* if we are already in shutdown, don't change state. */
856 if (m_state == state_release)
859 if (fe->getState(state))
862 if (state == iDVBFrontend::stateLock)
864 eDebug("OURSTATE: ok");
866 } else if (state == iDVBFrontend::stateTuning)
868 eDebug("OURSTATE: tuning");
869 ourstate = state_tuning;
870 } else if (state == iDVBFrontend::stateLostLock)
872 /* on managed channels, we try to retune in order to re-acquire lock. */
873 if (m_current_frontend_parameters)
875 eDebug("OURSTATE: lost lock, trying to retune");
876 ourstate = state_tuning;
877 m_frontend->get().tune(*m_current_frontend_parameters);
879 /* on unmanaged channels, we don't do this. the client will do this. */
881 eDebug("OURSTATE: lost lock, unavailable now.");
882 ourstate = state_unavailable;
884 } else if (state == iDVBFrontend::stateFailed)
886 eDebug("OURSTATE: failed");
887 ourstate = state_failed;
889 eFatal("state unknown");
891 if (ourstate != m_state)
894 m_stateChanged(this);
898 void eDVBChannel::pvrEvent(int event)
902 case eFilePushThread::evtEOF:
903 eDebug("eDVBChannel: End of file!");
904 m_event(this, evtEOF);
906 case eFilePushThread::evtUser: /* start */
908 m_event(this, evtSOF);
913 void eDVBChannel::cueSheetEvent(int event)
917 case eCueSheet::evtSeek:
919 flushPVR(m_cue->m_decoding_demux);
921 case eCueSheet::evtSkipmode:
924 m_cue->m_lock.WrLock();
925 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
926 m_cue->m_lock.Unlock();
927 eRdLocker l(m_cue->m_lock);
928 if (m_cue->m_skipmode_ratio)
930 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
931 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
932 /* i agree that this might look a bit like black magic. */
933 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
934 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
936 if (m_cue->m_skipmode_ratio < 0)
937 m_skipmode_m -= m_skipmode_n;
939 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
941 if (abs(m_skipmode_m) < abs(m_skipmode_n))
943 eWarning("something is wrong with this calculation");
944 m_skipmode_n = m_skipmode_m = 0;
949 eDebug("skipmode ratio is 0, normal play");
950 m_skipmode_n = m_skipmode_m = 0;
953 ASSERT(m_pvr_thread);
954 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
956 flushPVR(m_cue->m_decoding_demux);
960 case eCueSheet::evtSpanChanged:
962 m_source_span.clear();
963 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
965 off_t offset_in, offset_out;
966 pts_t pts_in = i->first, pts_out = i->second;
967 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
969 eDebug("span translation failed.\n");
972 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
973 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
980 /* align toward zero */
981 static inline long long align(long long x, int align)
996 /* remember, this gets called from another thread. */
997 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
999 const int blocksize = 188;
1000 unsigned int max = align(10*1024*1024, blocksize);
1001 current_offset = align(current_offset, blocksize);
1005 eDebug("no cue sheet. forcing normal play");
1006 start = current_offset;
1011 m_cue->m_lock.RdLock();
1012 if (!m_cue->m_decoding_demux)
1014 start = current_offset;
1016 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1017 m_cue->m_lock.Unlock();
1023 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1024 max = align(m_skipmode_n, blocksize);
1027 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1029 current_offset += align(m_skipmode_m, blocksize);
1031 while (!m_cue->m_seek_requests.empty())
1033 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1034 m_cue->m_lock.Unlock();
1035 m_cue->m_lock.WrLock();
1036 m_cue->m_seek_requests.pop_front();
1037 m_cue->m_lock.Unlock();
1038 m_cue->m_lock.RdLock();
1039 int relative = seek.first;
1040 pts_t pts = seek.second;
1045 if (!m_cue->m_decoder)
1047 eDebug("no decoder - can't seek relative");
1050 if (m_cue->m_decoder->getPTS(0, now))
1052 eDebug("decoder getPTS failed, can't seek relative");
1055 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1057 eDebug("seekTo: getCurrentPosition failed!");
1060 } else if (pts < 0) /* seek relative to end */
1063 if (!getLength(len))
1065 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1069 eWarning("getLength failed - can't seek relative to end!");
1074 if (relative == 1) /* pts relative */
1085 if (relative == 2) /* AP relative */
1087 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1089 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1091 pts = now - 90000; /* approx. 1s */
1092 eDebug("AP relative seeking failed!");
1095 eDebug("next ap is %llx\n", pts);
1101 if (m_tstools.getOffset(offset, pts))
1103 eDebug("get offset for pts=%lld failed!", pts);
1107 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1108 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1111 m_cue->m_lock.Unlock();
1113 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1115 long long aligned_start = align(i->first, blocksize);
1116 long long aligned_end = align(i->second, blocksize);
1118 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1120 start = current_offset;
1121 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1122 if ((aligned_end - current_offset) > max)
1125 size = aligned_end - current_offset;
1126 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1129 if (current_offset < aligned_start)
1131 /* ok, our current offset is in an 'out' zone. */
1132 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1134 /* in normal playback, just start at the next zone. */
1137 /* size is not 64bit! */
1138 if ((i->second - i->first) > max)
1141 size = aligned_end - aligned_start;
1144 if (m_skipmode_m < 0)
1146 eDebug("reached SOF");
1149 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1153 /* when skipping reverse, however, choose the zone before. */
1155 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1158 aligned_start = align(i->first, blocksize);
1159 aligned_end = align(i->second, blocksize);
1161 if ((aligned_end - aligned_start) > max)
1164 len = aligned_end - aligned_start;
1166 start = aligned_end - len;
1167 eDebug("skipping to %llx, %d", start, len);
1170 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1175 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1177 eDebug("reached SOF");
1179 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1182 start = current_offset;
1185 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1189 void eDVBChannel::AddUse()
1191 if (++m_use_count > 1 && m_state == state_last_instance)
1194 m_stateChanged(this);
1198 void eDVBChannel::ReleaseUse()
1202 m_state = state_release;
1203 m_stateChanged(this);
1205 else if (m_use_count == 1)
1207 m_state = state_last_instance;
1208 m_stateChanged(this);
1212 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1215 m_mgr->removeChannel(this);
1222 eDebug("no frontend to tune!");
1226 m_channel_id = channelid;
1227 m_mgr->addChannel(channelid, this);
1228 m_state = state_tuning;
1229 /* if tuning fails, shutdown the channel immediately. */
1231 res = m_frontend->get().tune(*feparm);
1232 m_current_frontend_parameters = feparm;
1236 m_state = state_release;
1237 m_stateChanged(this);
1244 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1246 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1250 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1252 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1256 RESULT eDVBChannel::getState(int &state)
1262 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1267 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1269 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1275 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1280 /* don't hold a reference to the decoding demux, we don't need it. */
1282 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1283 the refcount is lost. thus, decoding demuxes are never allocated.
1285 this poses a big problem for PiP. */
1286 if (cap & capDecode)
1291 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1296 frontend = &m_frontend->get();
1302 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1304 param = m_current_frontend_parameters;
1308 RESULT eDVBChannel::playFile(const char *file)
1310 ASSERT(!m_frontend);
1313 m_pvr_thread->stop();
1314 delete m_pvr_thread;
1318 m_tstools.openFile(file);
1320 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1321 THEN DO A REAL FIX HERE! */
1323 /* (this codepath needs to be improved anyway.) */
1324 #if HAVE_DVB_API_VERSION < 3
1325 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1327 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1329 if (m_pvr_fd_dst < 0)
1331 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1335 m_pvr_thread = new eDVBChannelFilePush();
1336 m_pvr_thread->enablePVRCommit(1);
1337 m_pvr_thread->setStreamMode(1);
1338 m_pvr_thread->setScatterGather(this);
1340 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1342 delete m_pvr_thread;
1344 eDebug("can't open PVR file %s (%m)", file);
1347 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1350 m_stateChanged(this);
1355 void eDVBChannel::stopFile()
1359 m_pvr_thread->stop();
1360 ::close(m_pvr_fd_dst);
1361 delete m_pvr_thread;
1366 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1368 m_conn_cueSheetEvent = 0;
1371 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1374 RESULT eDVBChannel::getLength(pts_t &len)
1376 return m_tstools.calcLen(len);
1379 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1381 if (!decoding_demux)
1388 if (mode == 0) /* demux */
1390 r = decoding_demux->getSTC(now, 0);
1393 eDebug("demux getSTC failed");
1397 now = pos; /* fixup supplied */
1399 off_t off = 0; /* TODO: fixme */
1400 r = m_tstools.fixupPTS(off, now);
1403 eDebug("fixup PTS failed");
1412 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1414 /* when seeking, we have to ensure that all buffers are flushed.
1415 there are basically 3 buffers:
1416 a.) the filepush's internal buffer
1417 b.) the PVR buffer (before demux)
1418 c.) the ratebuffer (after demux)
1420 it's important to clear them in the correct order, otherwise
1421 the ratebuffer (for example) would immediately refill from
1422 the not-yet-flushed PVR buffer.
1425 m_pvr_thread->pause();
1426 /* flush internal filepush buffer */
1427 m_pvr_thread->flush();
1428 /* HACK: flush PVR buffer */
1429 ::ioctl(m_pvr_fd_dst, 0);
1431 /* flush ratebuffers (video, audio) */
1433 decoding_demux->flush();
1435 /* demux will also flush all decoder.. */
1436 /* resume will re-query the SG */
1437 m_pvr_thread->resume();
1440 DEFINE_REF(eCueSheet);
1442 eCueSheet::eCueSheet()
1444 m_skipmode_ratio = 0;
1447 void eCueSheet::seekTo(int relative, const pts_t &pts)
1450 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1455 void eCueSheet::clear()
1462 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1465 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1469 void eCueSheet::commitSpans()
1471 m_event(evtSpanChanged);
1474 void eCueSheet::setSkipmode(const pts_t &ratio)
1477 m_skipmode_ratio = ratio;
1479 m_event(evtSkipmode);
1482 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1484 m_decoding_demux = demux;
1485 m_decoder = decoder;
1488 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1490 connection = new eConnection(this, m_event.connect(event));