X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/9c3098c8667241d18d2551a9a37ce7fbce396b71..a34ef895210161a8820e96829ac87806566e7858:/lib/dvb/pvrparse.cpp diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index a6113329..c7a37460 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -35,6 +35,7 @@ int eMPEGStreamInformation::load(const char *filename) if (!f) return -1; m_access_points.clear(); + m_pts_to_offset.clear(); while (1) { unsigned long long d[2]; @@ -46,6 +47,7 @@ int eMPEGStreamInformation::load(const char *filename) d[1] = bswap_64(d[1]); #endif m_access_points[d[0]] = d[1]; + m_pts_to_offset.insert(std::pair(d[1], d[0])); } fclose(f); fixupDiscontinuties(); @@ -123,7 +125,7 @@ pts_t eMPEGStreamInformation::getDelta(off_t offset) /* i can be the first when you query for something before the first PTS */ if (i != m_timestamp_deltas.begin()) --i; - + return i->second; } @@ -132,24 +134,29 @@ int eMPEGStreamInformation::fixupPTS(const off_t &offset, pts_t &ts) if (!m_timestamp_deltas.size()) 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()) + std::multimap::const_iterator + l = m_pts_to_offset.upper_bound(ts - 60 * 90000), + u = m_pts_to_offset.upper_bound(ts + 60 * 90000), + nearest = m_pts_to_offset.end(); + + while (l != u) { - if ((nearest == m_access_points.end()) || (llabs(i->second - ts) < llabs(nearest->second - ts))) - nearest = i; - ++i; + if ((nearest == m_pts_to_offset.end()) || (llabs(l->first - ts) < llabs(nearest->first - ts))) + nearest = l; + ++l; } - if (nearest == m_access_points.end()) - return -1; - ts -= getDelta(nearest->first); + if (nearest == m_pts_to_offset.end()) + return 1; + + ts -= getDelta(nearest->second); + 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; @@ -170,7 +177,6 @@ pts_t eMPEGStreamInformation::getInterpolated(off_t offset) { /* get the PTS values before and after the offset. */ std::map::iterator before, after; - after = m_access_points.upper_bound(offset); before = after; @@ -201,31 +207,45 @@ pts_t eMPEGStreamInformation::getInterpolated(off_t offset) return before_ts + diff; } -off_t eMPEGStreamInformation::getAccessPoint(pts_t ts) +off_t eMPEGStreamInformation::getAccessPoint(pts_t ts, int marg) { /* FIXME: more efficient implementation */ - pts_t delta = 0; off_t last = 0; + off_t last2 = 0; + pts_t lastc = 0; for (std::map::const_iterator i(m_access_points.begin()); i != m_access_points.end(); ++i) { pts_t delta = getDelta(i->first); pts_t c = i->second - delta; - if (c > ts) - break; + if (c > ts) { + if (marg > 0) + return (last + i->first)/376*188; + else if (marg < 0) + return (last + last2)/376*188; + else + return last; + } + lastc = c; + last2 = last; last = i->first; } - return last; + if (marg < 0) + return (last + last2)/376*188; + else + return last; } int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, int direction) { off_t offset = getAccessPoint(start); + pts_t c1, c2; std::map::const_iterator i = m_access_points.find(offset); if (i == m_access_points.end()) { eDebug("getNextAccessPoint: initial AP not found"); return -1; } + c1 = i->second - getDelta(i->first); while (direction) { if (direction > 0) @@ -233,6 +253,12 @@ int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, in if (i == m_access_points.end()) return -1; ++i; + c2 = i->second - getDelta(i->first); + if (c1 == c2) { // Discontinuity + ++i; + c2 = i->second - getDelta(i->first); + } + c1 = c2; direction--; } if (direction < 0) @@ -243,6 +269,12 @@ int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, in return -1; } --i; + c2 = i->second - getDelta(i->first); + if (c1 == c2) { // Discontinuity + --i; + c2 = i->second - getDelta(i->first); + } + c1 = c2; direction++; } } @@ -316,8 +348,16 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) /* advance to payload */ pkt += pkt[8] + 9; - + + /* sometimes, there are zeros before the startcode. */ + while (pkt < (end-4)) + if (pkt[0] || pkt[1] || pkt[2]) + break; + else + pkt++; + /* if startcode found */ +// eDebug("%02x %02x %02x %02x", pkt[0], pkt[1], pkt[2], pkt[3]); if (!(pkt[0] || pkt[1] || (pkt[2] != 1))) { if (pkt[3] == 0xb3) /* sequence header */ @@ -325,9 +365,20 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) if (ptsvalid) { m_streaminfo.m_access_points[offset] = pts; - eDebug("Sequence header at %llx, pts %llx", offset, pts); +// eDebug("Sequence header at %llx, pts %llx", offset, pts); + } else + /*eDebug("Sequence header but no valid PTS value.")*/; + } + + if (pkt[3] == 0x09 && /* MPEG4 AVC unit access delimiter */ + (pkt[4] >> 5) == 0) /* and I-frame */ + { + if (ptsvalid) + { + m_streaminfo.m_access_points[offset] = pts; +// eDebug("MPEG4 AVC UAD at %llx, pts %llx", offset, pts); } else - eDebug("Sequence header but no valid PTS value."); + /*eDebug("MPEG4 AVC UAD but no valid PTS value.")*/; } } return 0;