From ca329d3e86a98aacb0597d8581f5354cc99542e4 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Wed, 15 Feb 2006 01:20:15 +0000 Subject: [PATCH] use cached pts/offsets when available, clean up --- lib/dvb/dvb.cpp | 27 ++++++----------------- lib/dvb/pvrparse.cpp | 52 ++++++++++++++++++++++++++++++++------------ lib/dvb/pvrparse.h | 7 ++++-- lib/dvb/tstools.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++ lib/dvb/tstools.h | 18 +++++++++++++-- 5 files changed, 117 insertions(+), 38 deletions(-) diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index ad865c08..11b1285a 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -996,17 +996,8 @@ RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, in if (!decoding_demux) return -1; - off_t begin = 0; - /* getPTS for offset 0 is cached, so it doesn't harm. */ - int r = m_tstools.getPTS(begin, pos); - if (r) - { - eDebug("tstools getpts(0) failed!"); - return r; - } - pts_t now; - + int r; /* TODO: this is a gross hack. */ r = decoding_demux->getSTC(now, mode ? 128 : 0); @@ -1016,19 +1007,15 @@ RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, in return -1; } -// eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos); - /* when we are less than 10 seconds before the start, return 0. */ - /* (we're just waiting for the timespam to start) */ - if ((now < pos) && ((pos - now) < 90000 * 10)) + off_t off = 0; /* TODO: fixme */ + r = m_tstools.fixupPTS(off, now); + if (r) { - pos = 0; - return 0; + eDebug("fixup PTS failed"); + return -1; } - if (now < pos) /* wrap around */ - pos = now + 0x200000000LL - pos; - else - pos = now - pos; + pos = now; return 0; } diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 5d301373..58b215ba 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -63,7 +63,6 @@ void eMPEGStreamInformation::fixupDiscontinuties() if (!m_access_points.size()) return; - int first_is_unreliable = 0; eDebug("Fixing discontinuities ..."); /* if we have no delta at the beginning, extrapolate it */ @@ -78,7 +77,6 @@ void eMPEGStreamInformation::fixupDiscontinuties() tdiff *= first->first; tdiff /= diff; m_timestamp_deltas[0] = first->second - tdiff; - first_is_unreliable = 1; eDebug("first delta is %08llx", first->second - tdiff); } } @@ -91,9 +89,9 @@ void eMPEGStreamInformation::fixupDiscontinuties() { pts_t current = i->second - currentDelta; pts_t diff = current - lastpts_t; - if ((first_is_unreliable) || (diff > (90000*5))) // 5sec diff + + if (llabs(diff) > (90000*5)) // 5sec diff { - first_is_unreliable = 0; eDebug("%llx < %llx, have discont. new timestamp is %llx (diff is %llx)!", current, lastpts_t, i->second, diff); currentDelta = i->second - lastpts_t; /* FIXME: should be the extrapolated new timestamp, based on the current rate */ eDebug("current delta now %llx, making current to %llx", currentDelta, i->second - currentDelta); @@ -104,12 +102,16 @@ void eMPEGStreamInformation::fixupDiscontinuties() eDebug("ok, found %d disconts.", m_timestamp_deltas.size()); - - - for (off_t x=0; x < 1000000; x+= 100000) + +#if 0 + for (off_t x=0x25807E34ULL; x < 0x25B3CF70; x+= 100000) { - eDebug("%08llx -> %08llx | %08llx", x, getDelta(x), getInterpolated(x)); + off_t o = x; + pts_t p; + int r = getPTS(o, p); + eDebug("%08llx -> %08llx | %08llx, %d, %08llx %08llx", x, getDelta(x), getInterpolated(x), r, o, p); } +#endif } pts_t eMPEGStreamInformation::getDelta(off_t offset) @@ -125,11 +127,12 @@ pts_t eMPEGStreamInformation::getDelta(off_t offset) return i->second; } -pts_t eMPEGStreamInformation::fixuppts_t(off_t offset, pts_t ts) +int eMPEGStreamInformation::fixupPTS(const off_t &offset, pts_t &ts) { if (!m_timestamp_deltas.size()) - return 0; - std::map::const_iterator i = m_access_points.upper_bound(offset - 1024 * 1024), nearest = m_access_points.end(); + return -1; + + std::map::const_iterator i = m_access_points.upper_bound(offset - 4 * 1024 * 1024), nearest = m_access_points.end(); while (i != m_access_points.end()) { @@ -138,8 +141,29 @@ pts_t eMPEGStreamInformation::fixuppts_t(off_t offset, pts_t ts) ++i; } if (nearest == m_access_points.end()) - return 0; - return ts - getDelta(nearest->first); + return -1; + ts -= getDelta(nearest->first); + return 0; +} + +int eMPEGStreamInformation::getPTS(off_t &offset, pts_t &pts) +{ + std::map::iterator before = m_access_points.lower_bound(offset); + + /* usually, we prefer the AP before the given offset. however if there is none, we take any. */ + if (before != m_access_points.begin()) + --before; + + if (before == m_access_points.end()) + { + pts = 0; + return -1; + } + + offset = before->first; + pts = before->second - getDelta(offset); + + return 0; } pts_t eMPEGStreamInformation::getInterpolated(off_t offset) @@ -202,7 +226,7 @@ eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo): m_ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) { if (!wantPacket(pkt)) - printf("ne irgendwas ist da falsch\n"); + eWarning("something's wrong."); const unsigned char *end = pkt + 188; diff --git a/lib/dvb/pvrparse.h b/lib/dvb/pvrparse.h index 5ca6263d..7b586331 100644 --- a/lib/dvb/pvrparse.h +++ b/lib/dvb/pvrparse.h @@ -29,8 +29,11 @@ public: /* get delta at specific offset */ pts_t getDelta(off_t offset); - /* fixup timestamp near offset */ - pts_t fixuppts_t(off_t offset, pts_t ts); + /* fixup timestamp near offset, i.e. convert to zero-based */ + int fixupPTS(const off_t &offset, pts_t &ts); + + /* get PTS before offset */ + int getPTS(off_t &offset, pts_t &pts); /* inter/extrapolate timestamp from offset */ pts_t getInterpolated(off_t offset); diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index bec17a56..72a5f16f 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -13,6 +13,8 @@ eDVBTSTools::eDVBTSTools() m_begin_valid = 0; m_end_valid = 0; + + m_use_streaminfo = 0; } eDVBTSTools::~eDVBTSTools() @@ -23,6 +25,14 @@ eDVBTSTools::~eDVBTSTools() int eDVBTSTools::openFile(const char *filename) { closeFile(); + + m_streaminfo.load((std::string(filename) + ".ap").c_str()); + + if (!m_streaminfo.empty()) + m_use_streaminfo = 1; + else + m_use_streaminfo = 0; + m_fd = ::open(filename, O_RDONLY); if (m_fd < 0) return -1; @@ -48,6 +58,14 @@ void eDVBTSTools::setSearchRange(int maxrange) /* getPTS extracts a pts value from any PID at a given offset. */ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts) { + if (m_use_streaminfo) + { + off_t off = offset; + pts_t p = pts; + int r = m_streaminfo.getPTS(off, p); + eDebug("streaminfo result: %d, %08llx, %08llx", r, off, p); + } + if (m_fd < 0) return -1; @@ -112,6 +130,10 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts) pts |= ((unsigned long long)(pes[12]&0xFF)) << 7; pts |= ((unsigned long long)(pes[13]&0xFE)) >> 1; offset -= 188; + + /* convert to zero-based */ + fixupPTS(offset, pts); + eDebug("tstools result: %08llx, %08llx", offset, pts); return 0; } } @@ -119,6 +141,35 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts) return -1; } +int eDVBTSTools::fixupPTS(const off_t &offset, pts_t &now) +{ + if (m_use_streaminfo) + { + eDebug("streaminfo fixup, before %08llx", now); + int r = m_streaminfo.fixupPTS(offset, now); + eDebug("streaminfo fixup, after %08llx", now); + return r; + } else + { + /* for the simple case, we assume one epoch, with up to one wrap around in the middle. */ + calcBegin(); + off_t begin = 0; + pts_t pos; + if (getPTS(begin, pos)) + return -1; + if ((now < pos) && ((pos - now) < 90000 * 10)) + { + pos = 0; + return 0; + } + if (now < pos) /* wrap around */ + pos = now + 0x200000000LL - pos; + else + pos = now - pos; + return 0; + } +} + void eDVBTSTools::calcBegin() { if (m_fd < 0) diff --git a/lib/dvb/tstools.h b/lib/dvb/tstools.h index 95fbd9e2..55f86fbe 100644 --- a/lib/dvb/tstools.h +++ b/lib/dvb/tstools.h @@ -2,10 +2,11 @@ #define __lib_dvb_tstools_h #include +#include /* * Note: we're interested in PTS values, not STC values. - * thus we're not evaluating PES headers, not adaption fields. + * thus we're evaluating PES headers, not adaption fields. */ typedef long long pts_t; @@ -23,9 +24,19 @@ public: void setSearchRange(int maxrange); /* get first PTS *after* the given offset. */ + /* pts values are zero-based. */ int getPTS(off_t &offset, pts_t &pts); - int getPosition(off_t &offset, pts_t &pts); + /* this fixes up PTS to end up in a [0..len) range. + discontinuities etc. are handled here. + + input: + offset - approximate offset in file to resolve ambiguities + pts - video-pts (i.e. current STC of video decoder) + output: + pts - zero-based PTS value + */ + int fixupPTS(const off_t &offset, pts_t &pts); void calcBegin(); void calcEnd(); @@ -41,6 +52,9 @@ private: int m_begin_valid, m_end_valid; pts_t m_pts_begin, m_pts_end; off_t m_offset_begin, m_offset_end; + + eMPEGStreamInformation m_streaminfo; + int m_use_streaminfo; }; #endif -- 2.30.2