Patch by Anders Holst:
authorFelix Domke <tmbinc@elitedvb.net>
Fri, 31 Oct 2008 01:03:15 +0000 (02:03 +0100)
committerAndreas Oberritter <obi@saftware.de>
Thu, 6 Nov 2008 00:51:46 +0000 (01:51 +0100)
* Undo "sparse-AP-fix"

 At March 25 a patch was checked in that makes sure that AP:s closer
 than half a second from each other are filtered away. I don't know
 the exact purpose of this fix, but I don't think it is a good idea:
 Besides being the cause of bugs 4 and 5 above, all seek operations
 are based on the AP:s, and it is a pity to cripple the precision
 here. And for example, when cutting movies it is important to be
 able to reach the right GOP boundary. (And the next fix relies on
 all boundaries being available.) (If you wonder, bug 5 was caused by
 a destructive interaction of this with the discontinuity handling.)

* Hit GOP:s somewhat before GOP start

 It turns out that if you jump exactly to the GOP start, then that
 GOP is nevertheless skipped and playback starts from the GOP
 thereafter. However, if you jump to (at least) one frame before the
 GOP start, playback starts from that GOP. I don't know if this is a
 bug in the driver or elsewhere, but the best I can do is this
 workaround: Hit the GOP by jumping to half a GOP length before the
 GOP start. (By scanning the ts file it is of course possible to find
 the exact frame boundaries, but why bother since anywhere between
 the previous GOP start and the previous frame start will do.)
 Similarly, to show the first frame of a GOP, a few more frames must
 be included. Therefore, add half a GOP at the end of each source
 span.

* Jump over discontinuities during AP relative seek

 The above two fixes together *almost* take care of bugs 1 and 2
 above. Now seekRelative(1) moves one forward and seekRelative(-1) one
 backwards. However, at discontinuities they may get stuck. This is
 remedied by an extra if statement to check for discontinuities when
 stepping throught the AP:s in AP relative seek.

* Stop after last source span

 In the function eDVBChannel::getNextSourceSpan there was no code to
 take care of the case when the seeked-to point is after the last
 source span. Currently it just goes on until the movie ends. I have
 added code for this, which takes care of bug 3, and as a fortunate
 bonus effect bug 6 too. (But please check my code here, I hope I can
 use current_offset the way I do, and return 0 size when it should
 stop.)

lib/dvb/dvb.cpp
lib/dvb/pvrparse.cpp
lib/dvb/pvrparse.h
lib/dvb/tstools.cpp
lib/dvb/tstools.h

index 68d9a0dd958eca788b58826f508ce716eeb23a2a..6edf9e873b742adbec7ef2b6bb44b03332172a15 100644 (file)
@@ -1195,7 +1195,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;
@@ -1323,13 +1323,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;
@@ -1403,16 +1403,26 @@ 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 tmp = align(m_source_span.rbegin()->second, blocksize);
+               if (current_offset == tmp) {
+                       start = current_offset;
+                       size = 0;
+               } 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;
 }
index 1b827d3c03d8ac98ec81d52c08e5dfa01d1ac3e7..35ba909169a034298ac02a0fe5f9e7024e4f7d09 100644 (file)
@@ -36,8 +36,6 @@ int eMPEGStreamInformation::load(const char *filename)
                return -1;
        m_access_points.clear();
        m_pts_to_offset.clear();
-       pts_t last = -(1LL<<62);
-       int loaded = 0, skipped = 0;
        while (1)
        {
                unsigned long long d[2];
@@ -48,16 +46,9 @@ int eMPEGStreamInformation::load(const char *filename)
                d[0] = bswap_64(d[0]);
                d[1] = bswap_64(d[1]);
 #endif
-               if ((d[1] - last) > 90000/2)
-               {
-                       m_access_points[d[0]] = d[1];
-                       m_pts_to_offset.insert(std::pair<pts_t,off_t>(d[1], d[0]));
-                       last = d[1];
-                       loaded++;
-               } else
-                       skipped++;
+               m_access_points[d[0]] = d[1];
+               m_pts_to_offset.insert(std::pair<pts_t,off_t>(d[1], d[0]));
        }
-       eDebug("loaded %d, skipped %d", loaded, skipped);
        fclose(f);
        fixupDiscontinuties();
        return 0;
@@ -216,30 +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 */
        off_t last = 0;
+       off_t last2 = 0;
+       pts_t lastc = 0;
        for (std::map<off_t, pts_t>::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<off_t, pts_t>::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)
@@ -247,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)
@@ -257,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++;
                }
        }
index 69bb992401ac38aa0603585962e09f19edf91304..b2ddd23d56139a630021d76a44ef863a4fd1790a 100644 (file)
@@ -41,7 +41,7 @@ public:
                /* inter/extrapolate timestamp from offset */
        pts_t getInterpolated(off_t offset);
        
-       off_t getAccessPoint(pts_t ts);
+       off_t getAccessPoint(pts_t ts, int marg=0);
        
        int getNextAccessPoint(pts_t &ts, const pts_t &start, int direction);
        
index 5157ef2282927a38be806229fa1a40cd1b092440..bd7ebce2843be12e4bef4d6a1f12262b47555215 100644 (file)
@@ -209,11 +209,14 @@ int eDVBTSTools::fixupPTS(const off_t &offset, pts_t &now)
        }
 }
 
-int eDVBTSTools::getOffset(off_t &offset, pts_t &pts)
+int eDVBTSTools::getOffset(off_t &offset, pts_t &pts, int marg)
 {
        if (m_use_streaminfo)
        {
-               offset = m_streaminfo.getAccessPoint(pts);
+               if (pts >= m_pts_end && marg > 0 && m_end_valid)
+                       offset = m_offset_end;
+               else
+                       offset = m_streaminfo.getAccessPoint(pts, marg);
                return 0;
        } else
        {
index 1316825390391782b63b072e10a5deacfcb349a5..4bc04729c42056c3ab645ce46cb5a56249f0cb2f 100644 (file)
@@ -40,7 +40,7 @@ public:
        int fixupPTS(const off_t &offset, pts_t &pts);
        
                /* get (approximate) offset corresponding to PTS */
-       int getOffset(off_t &offset, pts_t &pts);
+       int getOffset(off_t &offset, pts_t &pts, int marg=0);
        
        int getNextAccessPoint(pts_t &ts, const pts_t &start, int direction);