+ if (!frame_skip_success)
+ {
+ current_offset += align(m_skipmode_m, blocksize);
+
+ if (m_skipmode_m)
+ {
+ eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
+ size_t iframe_len;
+ off_t iframe_start = current_offset;
+
+ int direction = (m_skipmode_m < 0) ? -1 : +1;
+ if (m_tstools.findFrame(iframe_start, iframe_len, direction))
+ eDebug("failed");
+ else
+ {
+ current_offset = align_with_len(iframe_start, blocksize, iframe_len);
+ max = align(iframe_len, blocksize);
+ }
+ }
+ }
+
+ while (!m_cue->m_seek_requests.empty())
+ {
+ std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
+ m_cue->m_lock.Unlock();
+ m_cue->m_lock.WrLock();
+ m_cue->m_seek_requests.pop_front();
+ m_cue->m_lock.Unlock();
+ m_cue->m_lock.RdLock();
+ int relative = seek.first;
+ pts_t pts = seek.second;
+
+ pts_t now = 0;
+ if (relative)
+ {
+ if (!m_cue->m_decoder)
+ {
+ eDebug("no decoder - can't seek relative");
+ continue;
+ }
+ if (m_cue->m_decoder->getPTS(0, now))
+ {
+ eDebug("decoder getPTS failed, can't seek relative");
+ continue;
+ }
+ if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
+ {
+ eDebug("seekTo: getCurrentPosition failed!");
+ continue;
+ }
+ } else if (pts < 0) /* seek relative to end */
+ {
+ pts_t len;
+ if (!getLength(len))
+ {
+ eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
+ pts += len;
+ } else
+ {
+ eWarning("getLength failed - can't seek relative to end!");
+ continue;
+ }
+ }
+
+ if (relative == 1) /* pts relative */
+ {
+ pts += now;
+ if (pts < 0)
+ pts = 0;
+ }
+
+ if (relative != 2)
+ if (pts < 0)
+ pts = 0;
+
+ if (relative == 2) /* AP relative */
+ {
+ eDebug("AP relative seeking: %lld, at %lld", pts, now);
+ pts_t nextap;
+ if (m_tstools.getNextAccessPoint(nextap, now, pts))
+ {
+ pts = now - 90000; /* approx. 1s */
+ eDebug("AP relative seeking failed!");
+ } else
+ {
+ pts = nextap;
+ eDebug("next ap is %llx\n", pts);
+ }
+ }
+
+ off_t offset = 0;
+ if (m_tstools.getOffset(offset, pts, -1))
+ {
+ eDebug("get offset for pts=%lld failed!", pts);
+ continue;
+ }
+
+ size_t iframe_len;
+ /* try to align to iframe */
+ int direction = pts < 0 ? -1 : 1;
+ m_tstools.findFrame(offset, iframe_len, direction);
+
+ eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx (skipped additional %d frames due to iframe re-align)", relative, pts, offset, direction);
+ current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
+ }
+
+ m_cue->m_lock.Unlock();
+
+ for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
+ {
+ long long aligned_start = align(i->first, blocksize);
+ long long aligned_end = align(i->second, blocksize);
+
+ if ((current_offset >= aligned_start) && (current_offset < aligned_end))
+ {
+ start = current_offset;
+ /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
+ if ((aligned_end - current_offset) > max)
+ size = max;
+ else
+ size = aligned_end - current_offset;
+ eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
+ return;
+ }
+ if (current_offset < aligned_start)
+ {
+ /* ok, our current offset is in an 'out' zone. */
+ if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
+ {
+ /* in normal playback, just start at the next zone. */
+ start = i->first;
+
+ /* size is not 64bit! */
+ if ((i->second - i->first) > max)
+ size = max;
+ else
+ size = aligned_end - aligned_start;
+
+ eDebug("skip");
+ if (m_skipmode_m < 0)
+ {
+ eDebug("reached SOF");
+ /* reached SOF */
+ m_skipmode_m = 0;
+ m_pvr_thread->sendEvent(eFilePushThread::evtUser);
+ }
+ } else
+ {
+ /* when skipping reverse, however, choose the zone before. */
+ --i;
+ eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
+ size_t len;
+
+ aligned_start = align(i->first, blocksize);
+ aligned_end = align(i->second, blocksize);
+
+ if ((aligned_end - aligned_start) > max)
+ len = max;
+ else
+ len = aligned_end - aligned_start;
+
+ start = aligned_end - len;
+ eDebug("skipping to %llx, %d", start, len);
+ }
+
+ eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
+ return;
+ }
+ }
+
+ 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())
+ {
+ start = current_offset;
+ size = max;
+ eDebug("NO CUESHEET. (%08llx, %d)", start, size);
+ } else
+ {
+ start = current_offset;
+ size = 0;
+ }
+ return;
+}
+
+void eDVBChannel::AddUse()
+{
+ if (++m_use_count > 1 && m_state == state_last_instance)
+ {
+ m_state = state_ok;
+ m_stateChanged(this);
+ }
+}
+
+void eDVBChannel::ReleaseUse()
+{
+ if (!--m_use_count)
+ {
+ m_state = state_release;
+ m_stateChanged(this);
+ }
+ else if (m_use_count == 1)
+ {
+ m_state = state_last_instance;
+ m_stateChanged(this);
+ }
+}
+
+RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
+{
+ if (m_channel_id)
+ m_mgr->removeChannel(this);
+
+ if (!channelid)
+ return 0;
+