X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/e4e7f6e8cec4e5e5c6646902a598fed377aa8cf2..a34ef895210161a8820e96829ac87806566e7858:/lib/dvb/dvb.cpp diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 11902507..3ad086de 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -61,11 +61,12 @@ ePtr NewResourceManagerPtr(void) } eDVBResourceManager::eDVBResourceManager() - :m_releaseCachedChannelTimer(eApp) + :m_releaseCachedChannelTimer(eTimer::create(eApp)) { avail = 1; busy = 0; - m_sec = new eDVBSatelliteEquipmentControl(m_frontend); + m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend); + if (!instance) instance = this; @@ -80,12 +81,12 @@ eDVBResourceManager::eDVBResourceManager() num_adapter++; } - eDebug("found %d adapter, %d frontends and %d demux", - m_adapter.size(), m_frontend.size(), m_demux.size()); + eDebug("found %d adapter, %d frontends(%d sim) and %d demux", + m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size()); eDVBCAService::registerChannelCallback(this); - CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel); + CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel); } void eDVBResourceManager::feStateChanged() @@ -117,10 +118,18 @@ eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr) break; ePtr fe; - int ok = 0; - fe = new eDVBFrontend(m_nr, num_fe, ok); - if (ok) - m_frontend.push_back(fe); + { + int ok = 0; + fe = new eDVBFrontend(m_nr, num_fe, ok); + if (ok) + m_frontend.push_back(fe); + } + { + int ok = 0; + fe = new eDVBFrontend(m_nr, num_fe, ok, true); + if (ok) + m_simulate_frontend.push_back(fe); + } ++num_fe; } @@ -173,9 +182,9 @@ int eDVBAdapterLinux::getNumFrontends() return m_frontend.size(); } -RESULT eDVBAdapterLinux::getFrontend(ePtr &fe, int nr) +RESULT eDVBAdapterLinux::getFrontend(ePtr &fe, int nr, bool simulate) { - eSmartPtrList::iterator i(m_frontend.begin()); + eSmartPtrList::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin()); while (nr && (i != m_frontend.end())) { --nr; @@ -249,6 +258,32 @@ void eDVBResourceManager::addAdapter(iDVBAdapter *adapter) } } } + + prev_dvbt_frontend = 0; + for (i=0; i frontend; + if (!adapter->getFrontend(frontend, i, true)) + { + int frontendType=0; + frontend->getFrontendType(frontendType); + eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter); +// CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged); + m_simulate_frontend.push_back(new_fe); + frontend->setSEC(m_sec); + // we must link all dvb-t frontends ( for active antenna voltage ) + if (frontendType == iDVBFrontend::feTerrestrial) + { + if (prev_dvbt_frontend) + { + prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe); + frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend)); + } + prev_dvbt_frontend = new_fe; + } + } + } + } PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list) @@ -273,16 +308,24 @@ PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list) if (!i->m_frontend->setSlotInfo(obj)) return NULL; } + pos=0; + for (eSmartPtrList::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i) + { + ePyObject obj = PyList_GET_ITEM(list, pos++); + if (!i->m_frontend->setSlotInfo(obj)) + return NULL; + } Py_RETURN_NONE; } -RESULT eDVBResourceManager::allocateFrontend(ePtr &fe, ePtr &feparm) +RESULT eDVBResourceManager::allocateFrontend(ePtr &fe, ePtr &feparm, bool simulate) { + eSmartPtrList &frontends = simulate ? m_simulate_frontend : m_frontend; ePtr best; int bestval = 0; int foundone = 0; - for (eSmartPtrList::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i) + for (eSmartPtrList::iterator i(frontends.begin()); i != frontends.end(); ++i) { int c = i->m_frontend->isCompatibleWith(feparm); @@ -291,12 +334,15 @@ RESULT eDVBResourceManager::allocateFrontend(ePtr &fe, eP if (!i->m_inuse) { +// eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c); if (c > bestval) { bestval = c; best = i; } } +// else +// eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c); } if (best) @@ -382,7 +428,7 @@ RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr unused; - if (m_demux.length() < 5) + if (m_demux.size() < 5) { /* FIXME: hardware demux policy */ if (!(cap & iDVBChannel::capDecode)) @@ -467,11 +513,24 @@ RESULT eDVBResourceManager::getChannelList(ePtr &list) return -ENOENT; } -RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr &channel) +#define eDebugNoSimulate(x...) \ + do { \ + if (!simulate) \ + eDebug(x); \ + } while(0) +// else \ +// { \ +// eDebugNoNewLine("SIMULATE:"); \ +// eDebug(x); \ +// } \ + + +RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr &channel, bool simulate) { /* first, check if a channel is already existing. */ + std::list &active_channels = simulate ? m_active_simulate_channels : m_active_channels; - if (m_cached_channel) + if (!simulate && m_cached_channel) { eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel); if(channelid==cache_chan->getChannelID()) @@ -482,33 +541,33 @@ RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUse } m_cached_channel_state_changed_conn.disconnect(); m_cached_channel=0; - m_releaseCachedChannelTimer.stop(); + m_releaseCachedChannelTimer->stop(); } -// eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get()); - for (std::list::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i) + eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get()); + for (std::list::iterator i(active_channels.begin()); i != active_channels.end(); ++i) { -// eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get()); + eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get()); if (i->m_channel_id == channelid) { -// eDebug("found shared channel.."); + eDebugNoSimulate("found shared channel.."); channel = i->m_channel; return 0; } } - + /* no currently available channel is tuned to this channelid. create a new one, if possible. */ if (!m_list) { - eDebug("no channel list set!"); + eDebugNoSimulate("no channel list set!"); return errNoChannelList; } ePtr feparm; if (m_list->getChannelFrontendData(channelid, feparm)) { - eDebug("channel not found!"); + eDebugNoSimulate("channel not found!"); return errChannelNotInList; } @@ -516,13 +575,12 @@ RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUse ePtr fe; - int err = allocateFrontend(fe, feparm); + int err = allocateFrontend(fe, feparm, simulate); if (err) return err; RESULT res; - ePtr ch; - ch = new eDVBChannel(this, fe); + ePtr ch = new eDVBChannel(this, fe); res = ch->setChannel(channelid, feparm); if (res) @@ -530,9 +588,15 @@ RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUse channel = 0; return errChidNotFound; } - m_cached_channel = channel = ch; - m_cached_channel_state_changed_conn = - CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged); + + if (simulate) + channel = ch; + else + { + m_cached_channel = channel = ch; + m_cached_channel_state_changed_conn = + CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged); + } return 0; } @@ -547,13 +611,13 @@ void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan) case iDVBChannel::state_ok: { eDebug("stop release channel timer"); - m_releaseCachedChannelTimer.stop(); + m_releaseCachedChannelTimer->stop(); break; } case iDVBChannel::state_last_instance: { eDebug("start release channel timer"); - m_releaseCachedChannelTimer.start(3000, true); + m_releaseCachedChannelTimer->start(3000, true); break; } default: // ignore all other events @@ -575,17 +639,14 @@ RESULT eDVBResourceManager::allocateRawChannel(eUsePtr &channel, in { m_cached_channel_state_changed_conn.disconnect(); m_cached_channel=0; - m_releaseCachedChannelTimer.stop(); + m_releaseCachedChannelTimer->stop(); } int err = allocateFrontendByIndex(fe, slot_index); if (err) return err; - eDVBChannel *ch; - ch = new eDVBChannel(this, fe); - - channel = ch; + channel = new eDVBChannel(this, fe); return 0; } @@ -594,42 +655,55 @@ RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr &channel) { ePtr demux; - if (m_cached_channel && m_releaseCachedChannelTimer.isActive()) + if (m_cached_channel && m_releaseCachedChannelTimer->isActive()) { m_cached_channel_state_changed_conn.disconnect(); m_cached_channel=0; - m_releaseCachedChannelTimer.stop(); + m_releaseCachedChannelTimer->stop(); } - eDVBChannel *ch; - ch = new eDVBChannel(this, 0); - - channel = ch; + channel = new eDVBChannel(this, 0); return 0; } RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch) { - m_active_channels.push_back(active_channel(chid, ch)); - /* emit */ m_channelAdded(ch); + ePtr fe; + if (!ch->getFrontend(fe)) + { + eDVBFrontend *frontend = (eDVBFrontend*)&(*fe); + if (frontend->is_simulate()) + m_active_simulate_channels.push_back(active_channel(chid, ch)); + else + { + m_active_channels.push_back(active_channel(chid, ch)); + /* emit */ m_channelAdded(ch); + } + } return 0; } RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch) { - int cnt = 0; - for (std::list::iterator i(m_active_channels.begin()); i != m_active_channels.end();) + ePtr fe; + if (!ch->getFrontend(fe)) { - if (i->m_channel == ch) + eDVBFrontend *frontend = (eDVBFrontend*)&(*fe); + std::list &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels; + int cnt = 0; + for (std::list::iterator i(active_channels.begin()); i != active_channels.end();) { - i = m_active_channels.erase(i); - ++cnt; - } else - ++i; + if (i->m_channel == ch) + { + i = active_channels.erase(i); + ++cnt; + } else + ++i; + } + ASSERT(cnt == 1); + if (cnt == 1) + return 0; } - ASSERT(cnt == 1); - if (cnt == 1) - return 0; return -ENOENT; } @@ -639,12 +713,13 @@ RESULT eDVBResourceManager::connectChannelAdded(const Slot1 & return 0; } -int eDVBResourceManager::canAllocateFrontend(ePtr &feparm) +int eDVBResourceManager::canAllocateFrontend(ePtr &feparm, bool simulate) { + eSmartPtrList &frontends = simulate ? m_simulate_frontend : m_frontend; ePtr best; int bestval = 0; - for (eSmartPtrList::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i) + for (eSmartPtrList::iterator i(frontends.begin()); i != frontends.end(); ++i) if (!i->m_inuse) { int c = i->m_frontend->isCompatibleWith(feparm); @@ -681,10 +756,11 @@ int tuner_type_channel_default(ePtr &channellist, const eDVBCha return 0; } -int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore) +int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate) { + std::list &active_channels = simulate ? m_active_simulate_channels : m_active_channels; int ret=0; - if (m_cached_channel) + if (!simulate && m_cached_channel) { eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel); if(channelid==cache_chan->getChannelID()) @@ -693,7 +769,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons /* first, check if a channel is already existing. */ // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get()); - for (std::list::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i) + for (std::list::iterator i(active_channels.begin()); i != active_channels.end(); ++i) { // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get()); if (i->m_channel_id == channelid) @@ -706,8 +782,9 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons int *decremented_cached_channel_fe_usecount=NULL, *decremented_fe_usecount=NULL; - for (std::list::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i) + for (std::list::iterator i(active_channels.begin()); i != active_channels.end(); ++i) { + eSmartPtrList &frontends = simulate ? m_simulate_frontend : m_frontend; // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get()); if (i->m_channel_id == ignore) { @@ -721,7 +798,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons ePtr fe; if (!i->m_channel->getFrontend(fe)) { - for (eSmartPtrList::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii) + for (eSmartPtrList::iterator ii(frontends.begin()); ii != frontends.end(); ++ii) { if ( &(*fe) == &(*ii->m_frontend) ) { @@ -748,7 +825,8 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons ePtr fe; if (!channel->getFrontend(fe)) { - for (eSmartPtrList::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii) + eSmartPtrList &frontends = simulate ? m_simulate_frontend : m_frontend; + for (eSmartPtrList::iterator ii(frontends.begin()); ii != frontends.end(); ++ii) { if ( &(*fe) == &(*ii->m_frontend) ) { @@ -778,7 +856,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons goto error; } - ret = canAllocateFrontend(feparm); + ret = canAllocateFrontend(feparm, simulate); error: if (decremented_fe_usecount) @@ -911,9 +989,9 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s unsigned char *ts = data + ts_offset; int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF; - if ((d[3] == 0) && (m_pid == pid)) /* picture start */ + if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */ { - int picture_type = (d[5] >> 3) & 7; + int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1); d += 4; // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid); @@ -957,10 +1035,20 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s } } else if ((d[3] & 0xF0) == 0xE0) /* video stream */ { - if (m_pid != pid) + /* verify that this is actually a PES header, not just some ES data */ + if (ts[1] & 0x40) /* PUSI set */ { - eDebug("now locked to pid %04x", pid); - m_pid = pid; + int payload_start = 4; + if (ts[3] & 0x20) /* adaptation field present */ + payload_start += ts[4] + 1; /* skip AF */ + if (payload_start == (offset%184)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */ + { + if (m_pid != pid) + { + eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]); + m_pid = pid; + } + } } // m_pid = 0x6e; d += 4; @@ -1121,7 +1209,7 @@ void eDVBChannel::cueSheetEvent(int event) { off_t offset_in, offset_out; pts_t pts_in = i->first, pts_out = i->second; - if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out)) + if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1)) { eDebug("span translation failed.\n"); continue; @@ -1249,13 +1337,13 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off eDebug("AP relative seeking failed!"); } else { - eDebug("next ap is %llx\n", pts); pts = nextap; + eDebug("next ap is %llx\n", pts); } } off_t offset = 0; - if (m_tstools.getOffset(offset, pts)) + if (m_tstools.getOffset(offset, pts, -1)) { eDebug("get offset for pts=%lld failed!", pts); continue; @@ -1329,16 +1417,29 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off } } - if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) - { - eDebug("reached SOF"); - m_skipmode_m = 0; - m_pvr_thread->sendEvent(eFilePushThread::evtUser); + if (m_source_span.empty()) { + if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) + { + eDebug("reached SOF"); + m_skipmode_m = 0; + m_pvr_thread->sendEvent(eFilePushThread::evtUser); + } + start = current_offset; + size = max; + } else { + off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize); + pts_t len; + getLength(len); + m_tstools.getOffset(tmp2, len, 1); + if (current_offset == tmp || current_offset == tmp2) { + start = tmp2; + size = max; + } else { + start = tmp - align(512*1024, blocksize); + size = align(512*1024, blocksize); + } } - start = current_offset; - size = max; - eDebug("END OF CUESHEET. (%08llx, %d)", start, size); return; }