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;
285 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
287 int c = i->m_frontend->isCompatibleWith(feparm);
289 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
304 fe = new eDVBAllocatedFrontend(best);
311 return errAllSourcesBusy;
313 return errNoSourceFound;
316 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
318 int err = errNoSourceFound;
319 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
320 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
322 // check if another slot linked to this is in use
323 eDVBRegisteredFrontend *satpos_depends_to_fe =
324 (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR];
325 if ( (int)satpos_depends_to_fe != -1 )
327 if (satpos_depends_to_fe->m_inuse)
329 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
330 err = errAllSourcesBusy;
331 goto alloc_fe_by_id_not_possible;
334 else // check linked tuners
336 eDVBRegisteredFrontend *next =
337 (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
338 while ( (int)next != -1 )
342 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
343 err = errAllSourcesBusy;
344 goto alloc_fe_by_id_not_possible;
346 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
348 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)
349 i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
350 while ( (int)prev != -1 )
354 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
355 err = errAllSourcesBusy;
356 goto alloc_fe_by_id_not_possible;
358 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
361 fe = new eDVBAllocatedFrontend(i);
364 alloc_fe_by_id_not_possible:
369 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
371 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
372 never use the first one unless we need a decoding demux. */
374 eDebug("allocate demux");
375 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
377 if (i == m_demux.end())
381 /* FIXME: hardware demux policy */
382 if (!(cap & iDVBChannel::capDecode))
384 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
391 for (; i != m_demux.end(); ++i, ++n)
393 int is_decode = n < 2;
395 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
397 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
399 if ((cap & iDVBChannel::capDecode) && !is_decode)
402 demux = new eDVBAllocatedDemux(i);
404 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
406 demux->get().setSourcePVR(0);
410 eDebug("demux not found");
414 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
420 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
429 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
431 /* first, check if a channel is already existing. */
433 if (m_cached_channel)
435 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
436 if(channelid==cache_chan->getChannelID())
438 eDebug("use cached_channel");
439 channel = m_cached_channel;
442 m_cached_channel_state_changed_conn.disconnect();
444 m_releaseCachedChannelTimer.stop();
447 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
448 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
450 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
451 if (i->m_channel_id == channelid)
453 // eDebug("found shared channel..");
454 channel = i->m_channel;
459 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
463 eDebug("no channel list set!");
464 return errNoChannelList;
467 ePtr<iDVBFrontendParameters> feparm;
468 if (m_list->getChannelFrontendData(channelid, feparm))
470 eDebug("channel not found!");
471 return errChannelNotInList;
474 /* allocate a frontend. */
476 ePtr<eDVBAllocatedFrontend> fe;
478 int err = allocateFrontend(fe, feparm);
483 ePtr<eDVBChannel> ch;
484 ch = new eDVBChannel(this, fe);
486 res = ch->setChannel(channelid, feparm);
490 return errChidNotFound;
492 m_cached_channel = channel = ch;
493 m_cached_channel_state_changed_conn =
494 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
499 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
502 chan->getState(state);
505 case iDVBChannel::state_release:
506 case iDVBChannel::state_ok:
508 eDebug("stop release channel timer");
509 m_releaseCachedChannelTimer.stop();
512 case iDVBChannel::state_last_instance:
514 eDebug("start release channel timer");
515 m_releaseCachedChannelTimer.start(3000, true);
518 default: // ignore all other events
523 void eDVBResourceManager::releaseCachedChannel()
525 eDebug("release cached channel (timer timeout)");
529 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
531 ePtr<eDVBAllocatedFrontend> fe;
533 if (m_cached_channel)
535 m_cached_channel_state_changed_conn.disconnect();
537 m_releaseCachedChannelTimer.stop();
540 int err = allocateFrontendByIndex(fe, slot_index);
545 ch = new eDVBChannel(this, fe);
552 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
554 ePtr<eDVBAllocatedDemux> demux;
556 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
558 m_cached_channel_state_changed_conn.disconnect();
560 m_releaseCachedChannelTimer.stop();
564 ch = new eDVBChannel(this, 0);
570 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
572 m_active_channels.push_back(active_channel(chid, ch));
573 /* emit */ m_channelAdded(ch);
577 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
580 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
582 if (i->m_channel == ch)
584 i = m_active_channels.erase(i);
595 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
597 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
601 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
603 ePtr<eDVBRegisteredFrontend> best;
606 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
609 int c = i->m_frontend->isCompatibleWith(feparm);
616 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
620 ePtr<iDVBFrontendParameters> feparm;
621 if (!channellist->getChannelFrontendData(chid, feparm))
624 if (!feparm->getSystem(system))
628 case iDVBFrontend::feSatellite:
630 case iDVBFrontend::feCable:
632 case iDVBFrontend::feTerrestrial:
643 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
646 if (m_cached_channel)
648 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
649 if(channelid==cache_chan->getChannelID())
650 return tuner_type_channel_default(m_list, channelid);
653 /* first, check if a channel is already existing. */
654 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
655 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
657 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
658 if (i->m_channel_id == channelid)
660 // eDebug("found shared channel..");
661 return tuner_type_channel_default(m_list, channelid);
665 int *decremented_cached_channel_fe_usecount=NULL,
666 *decremented_fe_usecount=NULL;
668 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
670 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
671 if (i->m_channel_id == ignore)
673 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
674 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
675 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
676 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
677 // or 2 when the cached channel is not equal to the compared channel
678 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
680 ePtr<iDVBFrontend> fe;
681 if (!i->m_channel->getFrontend(fe))
683 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
685 if ( &(*fe) == &(*ii->m_frontend) )
688 decremented_fe_usecount = &ii->m_inuse;
689 if (channel == &(*m_cached_channel))
690 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
700 if (!decremented_cached_channel_fe_usecount)
702 if (m_cached_channel)
704 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
705 if (channel->getUseCount() == 1)
707 ePtr<iDVBFrontend> fe;
708 if (!channel->getFrontend(fe))
710 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
712 if ( &(*fe) == &(*ii->m_frontend) )
715 decremented_cached_channel_fe_usecount = &ii->m_inuse;
724 decremented_cached_channel_fe_usecount=NULL;
726 ePtr<iDVBFrontendParameters> feparm;
730 eDebug("no channel list set!");
734 if (m_list->getChannelFrontendData(channelid, feparm))
736 eDebug("channel not found!");
740 ret = canAllocateFrontend(feparm);
743 if (decremented_fe_usecount)
744 ++(*decremented_fe_usecount);
745 if (decremented_cached_channel_fe_usecount)
746 ++(*decremented_cached_channel_fe_usecount);
751 class eDVBChannelFilePush: public eFilePushThread
754 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
756 int m_iframe_search, m_iframe_state, m_pid;
757 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
760 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
763 if (!m_iframe_search)
766 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
768 eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
770 unsigned char *d = data;
771 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
773 int offset = d - data;
774 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
775 unsigned char *ts = data + ts_offset;
776 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
778 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
780 int picture_type = (d[5] >> 3) & 7;
783 eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
785 if (m_iframe_state == 1)
787 /* we are allowing data, and stop allowing data on the next frame.
788 we now found a frame. so stop here. */
789 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
790 current_span_remaining = 0;
792 unsigned char *fts = ts + 188;
793 while (fts < (data + len))
796 fts[2] |= 0xff; /* drop packet */
800 return len; // ts_offset + 188; /* deliver this packet, but not more. */
803 if (picture_type != 1) /* we are only interested in I frames */
806 unsigned char *fts = data;
810 fts[2] |= 0xff; /* drop packet */
814 /* force payload only */
818 // memset(ts + 4, 0xFF, (offset % 188) - 4);
822 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
826 eDebug("now locked to pid %04x", pid);
836 if (m_iframe_state == 1)
839 return 0; /* we need find an iframe first */
845 DEFINE_REF(eDVBChannel);
847 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
849 m_frontend = frontend;
853 m_skipmode_n = m_skipmode_m = 0;
856 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
859 eDVBChannel::~eDVBChannel()
862 m_mgr->removeChannel(this);
867 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
869 int state, ourstate = 0;
871 /* if we are already in shutdown, don't change state. */
872 if (m_state == state_release)
875 if (fe->getState(state))
878 if (state == iDVBFrontend::stateLock)
880 eDebug("OURSTATE: ok");
882 } else if (state == iDVBFrontend::stateTuning)
884 eDebug("OURSTATE: tuning");
885 ourstate = state_tuning;
886 } else if (state == iDVBFrontend::stateLostLock)
888 /* on managed channels, we try to retune in order to re-acquire lock. */
889 if (m_current_frontend_parameters)
891 eDebug("OURSTATE: lost lock, trying to retune");
892 ourstate = state_tuning;
893 m_frontend->get().tune(*m_current_frontend_parameters);
895 /* on unmanaged channels, we don't do this. the client will do this. */
897 eDebug("OURSTATE: lost lock, unavailable now.");
898 ourstate = state_unavailable;
900 } else if (state == iDVBFrontend::stateFailed)
902 eDebug("OURSTATE: failed");
903 ourstate = state_failed;
905 eFatal("state unknown");
907 if (ourstate != m_state)
910 m_stateChanged(this);
914 void eDVBChannel::pvrEvent(int event)
918 case eFilePushThread::evtEOF:
919 eDebug("eDVBChannel: End of file!");
920 m_event(this, evtEOF);
922 case eFilePushThread::evtUser: /* start */
924 m_event(this, evtSOF);
929 void eDVBChannel::cueSheetEvent(int event)
933 case eCueSheet::evtSeek:
935 flushPVR(m_cue->m_decoding_demux);
937 case eCueSheet::evtSkipmode:
940 m_cue->m_lock.WrLock();
941 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
942 m_cue->m_lock.Unlock();
943 eRdLocker l(m_cue->m_lock);
944 if (m_cue->m_skipmode_ratio)
946 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
947 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
948 /* i agree that this might look a bit like black magic. */
949 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
950 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
952 if (m_cue->m_skipmode_ratio < 0)
953 m_skipmode_m -= m_skipmode_n;
955 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
957 if (abs(m_skipmode_m) < abs(m_skipmode_n))
959 eWarning("something is wrong with this calculation");
960 m_skipmode_n = m_skipmode_m = 0;
965 eDebug("skipmode ratio is 0, normal play");
966 m_skipmode_n = m_skipmode_m = 0;
969 ASSERT(m_pvr_thread);
970 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
972 flushPVR(m_cue->m_decoding_demux);
976 case eCueSheet::evtSpanChanged:
978 m_source_span.clear();
979 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
981 off_t offset_in, offset_out;
982 pts_t pts_in = i->first, pts_out = i->second;
983 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
985 eDebug("span translation failed.\n");
988 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
989 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
996 /* align toward zero */
997 static inline long long align(long long x, int align)
1012 /* remember, this gets called from another thread. */
1013 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1015 const int blocksize = 188;
1016 unsigned int max = align(10*1024*1024, blocksize);
1017 current_offset = align(current_offset, blocksize);
1021 eDebug("no cue sheet. forcing normal play");
1022 start = current_offset;
1027 m_cue->m_lock.RdLock();
1028 if (!m_cue->m_decoding_demux)
1030 start = current_offset;
1032 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1033 m_cue->m_lock.Unlock();
1039 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1040 max = align(m_skipmode_n, blocksize);
1043 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1045 current_offset += align(m_skipmode_m, blocksize);
1047 while (!m_cue->m_seek_requests.empty())
1049 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1050 m_cue->m_lock.Unlock();
1051 m_cue->m_lock.WrLock();
1052 m_cue->m_seek_requests.pop_front();
1053 m_cue->m_lock.Unlock();
1054 m_cue->m_lock.RdLock();
1055 int relative = seek.first;
1056 pts_t pts = seek.second;
1061 if (!m_cue->m_decoder)
1063 eDebug("no decoder - can't seek relative");
1066 if (m_cue->m_decoder->getPTS(0, now))
1068 eDebug("decoder getPTS failed, can't seek relative");
1071 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1073 eDebug("seekTo: getCurrentPosition failed!");
1076 } else if (pts < 0) /* seek relative to end */
1079 if (!getLength(len))
1081 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1085 eWarning("getLength failed - can't seek relative to end!");
1090 if (relative == 1) /* pts relative */
1101 if (relative == 2) /* AP relative */
1103 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1105 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1107 pts = now - 90000; /* approx. 1s */
1108 eDebug("AP relative seeking failed!");
1111 eDebug("next ap is %llx\n", pts);
1117 if (m_tstools.getOffset(offset, pts))
1119 eDebug("get offset for pts=%lld failed!", pts);
1123 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1124 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1127 m_cue->m_lock.Unlock();
1129 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1131 long long aligned_start = align(i->first, blocksize);
1132 long long aligned_end = align(i->second, blocksize);
1134 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1136 start = current_offset;
1137 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1138 if ((aligned_end - current_offset) > max)
1141 size = aligned_end - current_offset;
1142 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1145 if (current_offset < aligned_start)
1147 /* ok, our current offset is in an 'out' zone. */
1148 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1150 /* in normal playback, just start at the next zone. */
1153 /* size is not 64bit! */
1154 if ((i->second - i->first) > max)
1157 size = aligned_end - aligned_start;
1160 if (m_skipmode_m < 0)
1162 eDebug("reached SOF");
1165 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1169 /* when skipping reverse, however, choose the zone before. */
1171 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1174 aligned_start = align(i->first, blocksize);
1175 aligned_end = align(i->second, blocksize);
1177 if ((aligned_end - aligned_start) > max)
1180 len = aligned_end - aligned_start;
1182 start = aligned_end - len;
1183 eDebug("skipping to %llx, %d", start, len);
1186 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1191 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1193 eDebug("reached SOF");
1195 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1198 start = current_offset;
1201 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1205 void eDVBChannel::AddUse()
1207 if (++m_use_count > 1 && m_state == state_last_instance)
1210 m_stateChanged(this);
1214 void eDVBChannel::ReleaseUse()
1218 m_state = state_release;
1219 m_stateChanged(this);
1221 else if (m_use_count == 1)
1223 m_state = state_last_instance;
1224 m_stateChanged(this);
1228 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1231 m_mgr->removeChannel(this);
1238 eDebug("no frontend to tune!");
1242 m_channel_id = channelid;
1243 m_mgr->addChannel(channelid, this);
1244 m_state = state_tuning;
1245 /* if tuning fails, shutdown the channel immediately. */
1247 res = m_frontend->get().tune(*feparm);
1248 m_current_frontend_parameters = feparm;
1252 m_state = state_release;
1253 m_stateChanged(this);
1260 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1262 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1266 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1268 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1272 RESULT eDVBChannel::getState(int &state)
1278 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1283 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1285 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1291 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1296 /* don't hold a reference to the decoding demux, we don't need it. */
1298 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1299 the refcount is lost. thus, decoding demuxes are never allocated.
1301 this poses a big problem for PiP. */
1302 if (cap & capDecode)
1307 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1312 frontend = &m_frontend->get();
1318 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1320 param = m_current_frontend_parameters;
1324 RESULT eDVBChannel::playFile(const char *file)
1326 ASSERT(!m_frontend);
1329 m_pvr_thread->stop();
1330 delete m_pvr_thread;
1334 m_tstools.openFile(file);
1336 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1337 THEN DO A REAL FIX HERE! */
1339 /* (this codepath needs to be improved anyway.) */
1340 #if HAVE_DVB_API_VERSION < 3
1341 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1343 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1345 if (m_pvr_fd_dst < 0)
1347 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1351 m_pvr_thread = new eDVBChannelFilePush();
1352 m_pvr_thread->enablePVRCommit(1);
1353 m_pvr_thread->setStreamMode(1);
1354 m_pvr_thread->setScatterGather(this);
1356 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1358 delete m_pvr_thread;
1360 eDebug("can't open PVR file %s (%m)", file);
1363 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1366 m_stateChanged(this);
1371 void eDVBChannel::stopFile()
1375 m_pvr_thread->stop();
1376 ::close(m_pvr_fd_dst);
1377 delete m_pvr_thread;
1382 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1384 m_conn_cueSheetEvent = 0;
1387 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1390 RESULT eDVBChannel::getLength(pts_t &len)
1392 return m_tstools.calcLen(len);
1395 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1397 if (!decoding_demux)
1404 if (mode == 0) /* demux */
1406 r = decoding_demux->getSTC(now, 0);
1409 eDebug("demux getSTC failed");
1413 now = pos; /* fixup supplied */
1415 off_t off = 0; /* TODO: fixme */
1416 r = m_tstools.fixupPTS(off, now);
1419 eDebug("fixup PTS failed");
1428 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1430 /* when seeking, we have to ensure that all buffers are flushed.
1431 there are basically 3 buffers:
1432 a.) the filepush's internal buffer
1433 b.) the PVR buffer (before demux)
1434 c.) the ratebuffer (after demux)
1436 it's important to clear them in the correct order, otherwise
1437 the ratebuffer (for example) would immediately refill from
1438 the not-yet-flushed PVR buffer.
1441 m_pvr_thread->pause();
1442 /* flush internal filepush buffer */
1443 m_pvr_thread->flush();
1444 /* HACK: flush PVR buffer */
1445 ::ioctl(m_pvr_fd_dst, 0);
1447 /* flush ratebuffers (video, audio) */
1449 decoding_demux->flush();
1451 /* demux will also flush all decoder.. */
1452 /* resume will re-query the SG */
1453 m_pvr_thread->resume();
1456 DEFINE_REF(eCueSheet);
1458 eCueSheet::eCueSheet()
1460 m_skipmode_ratio = 0;
1463 void eCueSheet::seekTo(int relative, const pts_t &pts)
1466 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1471 void eCueSheet::clear()
1478 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1481 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1485 void eCueSheet::commitSpans()
1487 m_event(evtSpanChanged);
1490 void eCueSheet::setSkipmode(const pts_t &ratio)
1493 m_skipmode_ratio = ratio;
1495 m_event(evtSkipmode);
1498 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1500 m_decoding_demux = demux;
1501 m_decoder = decoder;
1504 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1506 connection = new eConnection(this, m_event.connect(event));