X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/ecd8882f14e3ad6ebfc27be40dc71d110fe278c1..a34ef895210161a8820e96829ac87806566e7858:/lib/dvb/dvb.cpp diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index f5eadda0..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) @@ -320,10 +366,11 @@ RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index) { // check if another slot linked to this is in use - eDVBRegisteredFrontend *satpos_depends_to_fe = - (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR]; - if ( (long)satpos_depends_to_fe != -1 ) + long tmp; + i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp); + if ( tmp != -1 ) { + eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp; if (satpos_depends_to_fe->m_inuse) { eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!"); @@ -333,29 +380,29 @@ RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr } else // check linked tuners { - eDVBRegisteredFrontend *next = - (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR]; - while ( (long)next != -1 ) + i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp); + while ( tmp != -1 ) { + eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp; if (next->m_inuse) { eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!"); err = errAllSourcesBusy; goto alloc_fe_by_id_not_possible; } - next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR]; + next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp); } - eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) - i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR]; - while ( (long)prev != -1 ) + i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp); + while ( tmp != -1 ) { + eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp; if (prev->m_inuse) { eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!"); err = errAllSourcesBusy; goto alloc_fe_by_id_not_possible; } - prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR]; + prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp); } } fe = new eDVBAllocatedFrontend(i); @@ -373,40 +420,80 @@ RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr::iterator i(m_demux.begin()); - + + int n=0; + if (i == m_demux.end()) return -1; - - int n=0; - /* FIXME: hardware demux policy */ - if (!(cap & iDVBChannel::capDecode)) + + ePtr unused; + + if (m_demux.size() < 5) { - if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */ + /* FIXME: hardware demux policy */ + if (!(cap & iDVBChannel::capDecode)) { - ++i, ++n; - ++i, ++n; + if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */ + { + ++i, ++n; + ++i, ++n; + } } - } - - for (; i != m_demux.end(); ++i, ++n) - { - int is_decode = n < 2; + + for (; i != m_demux.end(); ++i, ++n) + { + int is_decode = n < 2; - int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse; + int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse; - if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter))) + if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter))) + { + if ((cap & iDVBChannel::capDecode) && !is_decode) + continue; + unused = i; + break; + } + } + } + else // we asume dm8000 + { + for (; i != m_demux.end(); ++i, ++n) { - if ((cap & iDVBChannel::capDecode) && !is_decode) - continue; - - demux = new eDVBAllocatedDemux(i); if (fe) - demux->get().setSourceFrontend(fe->m_frontend->getDVBID()); - else - demux->get().setSourcePVR(0); - return 0; + { + if (!i->m_inuse) + { + if (!unused) + unused = i; + } + else if (i->m_adapter == fe->m_adapter && + i->m_demux->getSource() == fe->m_frontend->getDVBID()) + { + demux = new eDVBAllocatedDemux(i); + return 0; + } + } + else if (n == 4) // always use demux4 for PVR (demux 4 can not descramble...) + { + if (i->m_inuse) { + demux = new eDVBAllocatedDemux(i); + return 0; + } + unused = i; + } } } + + if (unused) + { + demux = new eDVBAllocatedDemux(unused); + if (fe) + demux->get().setSourceFrontend(fe->m_frontend->getDVBID()); + else + demux->get().setSourcePVR(0); + return 0; + } + eDebug("demux not found"); return -1; } @@ -426,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()) @@ -441,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; } @@ -475,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) @@ -489,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; } @@ -506,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 @@ -534,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; } @@ -553,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; } @@ -598,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); @@ -640,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()) @@ -652,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) @@ -665,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) { @@ -680,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) ) { @@ -707,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) ) { @@ -737,7 +856,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons goto error; } - ret = canAllocateFrontend(feparm); + ret = canAllocateFrontend(feparm, simulate); error: if (decremented_fe_usecount) @@ -748,6 +867,15 @@ error: return ret; } +bool eDVBResourceManager::canMeasureFrontendInputPower() +{ + for (eSmartPtrList::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i) + { + return i->m_frontend->readInputpower() >= 0; + } + return false; +} + class eDVBChannelFilePush: public eFilePushThread { public: @@ -861,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); @@ -907,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; @@ -1014,6 +1152,9 @@ void eDVBChannel::pvrEvent(int event) void eDVBChannel::cueSheetEvent(int event) { + /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */ + if (!m_pvr_thread) + return; switch (event) { case eCueSheet::evtSeek: @@ -1051,7 +1192,6 @@ void eDVBChannel::cueSheetEvent(int event) m_skipmode_n = m_skipmode_m = 0; } } - ASSERT(m_pvr_thread); m_pvr_thread->setIFrameSearch(m_skipmode_n != 0); if (m_cue->m_skipmode_ratio != 0) m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */ @@ -1069,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; @@ -1197,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; @@ -1277,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; }