From 4a7a8362a83b1a6c2bd0abf13cd7b19359e9768a Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Thu, 29 Oct 2009 01:47:49 +0100 Subject: By Anders Holst: * My previous code for "slow rewind" (aka "SeekBackHack") is not required any more. Indeed, since the change in "decoder states" some time ago my code stopped working and is now only destructively interfering with the new winding approach, effectively ruining the speed accuracy for slow rewind. Similarly, the "non-smooth winding" code ruins the accuracy for high winding speeds. The patch below removes the "SeekBackHack", and temporarily disables the "non-smooth winding" code until we know whether the decoder states will allow simultaneous repeat and skip rates again. (InfoBarGenerics.py) * Due to a bug in 'eDVBTSTools::findNextPicture', rewind was always at the required speed minus one. (The frame just played was counted as one when skipping backwards.) Fixed below. (tstools.cpp) * A piece of code to apparently increase precision in seeking, by always aligning to an i-frame start, had exactly the opposite effect: GOP single-stepping fails completely on DM7025 and gets highly unreliable on DM800. The piece of code is removed. (It destructively interferes with previous code by me to hit frames somewhat before the GOP start. As an alternative, my previous code can be removed instead, and the currently removed piece of code adjusted to work. But then it has to be done differently on the two platforms.) (dvb.cpp) * By some reason eDVBVideo::getPTS only returns even numbers on DM800 even when it should be odd. This ruins GOP single stepping in 50% of the cases. This is easy to compensate for by adding a margin of 1 in getAccessPoint. (pvrparse.cpp) * After the above, when GOP single-stepping works reliable on both platforms and on SD/HD, the correct step lengths can be used. (InfoBarGenerics.py) --- lib/dvb/dvb.cpp | 7 +------ lib/dvb/pvrparse.cpp | 1 + lib/dvb/tstools.cpp | 21 ++++++++++++++++----- lib/python/Screens/InfoBarGenerics.py | 31 ++++++++++++------------------- 4 files changed, 30 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 894287e8..a8dfb193 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -1462,12 +1462,7 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off 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); + eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset); current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */ } diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 1393bf77..5cdecbd6 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -244,6 +244,7 @@ off_t eMPEGStreamInformation::getAccessPoint(pts_t ts, int marg) off_t last = 0; off_t last2 = 0; pts_t lastc = 0; + ts += 1; // Add rounding error margin for (std::map::const_iterator i(m_access_points.begin()); i != m_access_points.end(); ++i) { pts_t delta = getDelta(i->first); diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index a9eef406..2e5c5665 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -652,18 +652,23 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int frame_types) { - int nr_frames = 0; + int nr_frames, direction; // eDebug("trying to move %d frames at %llx", distance, offset); frame_types = frametypeI; /* TODO: intelligent "allow IP frames when not crossing an I-Frame */ - int direction = distance > 0 ? 0 : -1; - distance = abs(distance); - off_t new_offset = offset; size_t new_len = len; int first = 1; + if (distance > 0) { + direction = 0; + nr_frames = 0; + } else { + direction = -1; + nr_frames = -1; + distance = -distance+1; + } while (distance > 0) { int dir = direction; @@ -677,12 +682,18 @@ int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int // eDebug("we moved %d, %d to go frames (now at %llx)", dir, distance, new_offset); - if (distance >= 0 || first) + if (distance >= 0 || direction == 0) { first = 0; offset = new_offset; len = new_len; nr_frames += abs(dir); + } + else if (first) { + first = 0; + offset = new_offset; + len = new_len; + nr_frames += abs(dir) + distance; // never jump forward during rewind } } diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 2f830616..5336f9a0 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -692,8 +692,6 @@ class InfoBarSeek: iPlayableService.evSOF: self.__evSOF, }) - self.minSpeedBackward = useSeekBackHack and 16 or 0 - class InfoBarSeekActionMap(HelpableActionMap): def __init__(self, screen, *args, **kwargs): HelpableActionMap.__init__(self, screen, *args, **kwargs) @@ -740,24 +738,19 @@ class InfoBarSeek: self.__seekableStatusChanged() def makeStateForward(self, n): - minspeed = config.seek.stepwise_minspeed.value - repeat = int(config.seek.stepwise_repeat.value) - if minspeed != "Never" and n >= int(minspeed) and repeat > 1: - return (0, n * repeat, repeat, ">> %dx" % n) - else: +# minspeed = config.seek.stepwise_minspeed.value +# repeat = int(config.seek.stepwise_repeat.value) +# if minspeed != "Never" and n >= int(minspeed) and repeat > 1: +# return (0, n * repeat, repeat, ">> %dx" % n) +# else: return (0, n, 0, ">> %dx" % n) def makeStateBackward(self, n): - minspeed = config.seek.stepwise_minspeed.value - repeat = int(config.seek.stepwise_repeat.value) - if self.minSpeedBackward and n < self.minSpeedBackward: - r = (self.minSpeedBackward - 1)/ n + 1 - if minspeed != "Never" and n >= int(minspeed) and repeat > 1: - r = max(r, repeat) - return (0, -n * r, r, "<< %dx" % n) - elif minspeed != "Never" and n >= int(minspeed) and repeat > 1: - return (0, -n * repeat, repeat, "<< %dx" % n) - else: +# minspeed = config.seek.stepwise_minspeed.value +# repeat = int(config.seek.stepwise_repeat.value) +# if minspeed != "Never" and n >= int(minspeed) and repeat > 1: +# return (0, -n * repeat, repeat, "<< %dx" % n) +# else: return (0, -n, 0, "<< %dx" % n) def makeStateSlowMotion(self, n): @@ -877,7 +870,7 @@ class InfoBarSeek: if config.seek.on_pause.value == "play": self.unPauseService() elif config.seek.on_pause.value == "step": - self.doSeekRelative(0) + self.doSeekRelative(1) elif config.seek.on_pause.value == "last": self.setSeekState(self.lastseekstate) self.lastseekstate = self.SEEK_STATE_PLAY @@ -950,7 +943,7 @@ class InfoBarSeek: self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value))) self.doSeekRelative(-6) elif seekstate == self.SEEK_STATE_PAUSE: - self.doSeekRelative(-3) + self.doSeekRelative(-1) elif self.isStateForward(seekstate): speed = seekstate[1] if seekstate[2]: -- cgit v1.2.3 From 63aca7b44b8442376787481b35b1d141b8faef35 Mon Sep 17 00:00:00 2001 From: ghost Date: Mon, 23 Nov 2009 10:26:49 +0100 Subject: servicedvb.cpp: more exact resume after seek and slowmotion --- lib/service/servicedvb.cpp | 38 ++++++++++++++++++++++++++------------ lib/service/servicedvb.h | 4 +++- 2 files changed, 29 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 1a28fbdd..a3e479bf 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -917,7 +917,7 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv m_is_pvr = !m_reference.path.empty(); m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0; - m_skipmode = 0; + m_skipmode = m_fastforward = m_slowmotion = 0; CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent); CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift); @@ -1185,7 +1185,10 @@ RESULT eDVBServicePlay::setSlowMotion(int ratio) eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio); setFastForward_internal(0); if (m_decoder) + { + m_slowmotion = ratio; return m_decoder->setSlowMotion(ratio); + } else return -1; } @@ -1197,10 +1200,11 @@ RESULT eDVBServicePlay::setFastForward(int ratio) return setFastForward_internal(ratio); } -RESULT eDVBServicePlay::setFastForward_internal(int ratio) +RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek) { - int skipmode, ffratio; - + int skipmode, ffratio, ret = 0; + pts_t pos=0; + if (ratio > 8) { skipmode = ratio; @@ -1225,19 +1229,28 @@ RESULT eDVBServicePlay::setFastForward_internal(int ratio) if (m_cue) m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */ } - + m_skipmode = skipmode; - + + if (final_seek) + eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos); + + m_fastforward = ffratio; + if (!m_decoder) return -1; - + if (ffratio == 0) ; /* return m_decoder->play(); is done in caller*/ else if (ffratio != 1) - return m_decoder->setFastForward(ffratio); + ret = m_decoder->setFastForward(ffratio); else - return m_decoder->setTrickmode(); - return 0; + ret = m_decoder->setTrickmode(); + + if (pos) + eDebug("final seek after trickplay ret %d", seekTo(pos)); + + return ret; } RESULT eDVBServicePlay::seek(ePtr &ptr) @@ -1278,9 +1291,10 @@ RESULT eDVBServicePlay::pause() RESULT eDVBServicePlay::unpause() { eDebug("eDVBServicePlay::unpause"); - setFastForward_internal(0); + setFastForward_internal(0, m_slowmotion || m_fastforward > 1); if (m_decoder) { + m_slowmotion = 0; m_is_paused = 0; return m_decoder->play(); } else @@ -2229,7 +2243,7 @@ void eDVBServicePlay::switchToLive() m_new_subtitle_page_connection = 0; m_rds_decoder_event_connection = 0; m_video_event_connection = 0; - m_is_paused = m_skipmode = 0; /* not supported in live mode */ + m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */ /* free the timeshift service handler, we need the resources */ m_service_handler_timeshift.free(); diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h index b4d0f196..e3c7fd58 100644 --- a/lib/service/servicedvb.h +++ b/lib/service/servicedvb.h @@ -220,7 +220,7 @@ private: int m_current_audio_stream; int selectAudioStream(int n = -1); - RESULT setFastForward_internal(int ratio); + RESULT setFastForward_internal(int ratio, bool final_seek=false); /* timeshift */ ePtr m_record; @@ -233,6 +233,8 @@ private: void updateDecoder(); int m_skipmode; + int m_fastforward; + int m_slowmotion; /* cuesheet */ -- cgit v1.2.3 From 5e7190db5e448aaebd7d41ce94eb16760f729f1d Mon Sep 17 00:00:00 2001 From: ghost Date: Thu, 26 Nov 2009 14:34:55 +0100 Subject: servicedvb.cpp: fix transition from slowmotion or decoder fast forward to pause --- lib/service/servicedvb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index a3e479bf..21effd57 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1279,9 +1279,10 @@ RESULT eDVBServicePlay::getLength(pts_t &len) RESULT eDVBServicePlay::pause() { eDebug("eDVBServicePlay::pause"); - setFastForward_internal(0); + setFastForward_internal(0, m_slowmotion || m_fastforward > 1); if (m_decoder) { + m_slowmotion = 0; m_is_paused = 1; return m_decoder->pause(); } else -- cgit v1.2.3 From 99a717e9813eab30cd34f5da6f4a5ab6e791dc1f Mon Sep 17 00:00:00 2001 From: ghost Date: Thu, 26 Nov 2009 18:34:31 +0100 Subject: servicedvb.cpp: fix "some seconds no audio after audio track change on TS Playback" --- lib/service/servicedvb.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 21effd57..b71271a9 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1743,6 +1743,7 @@ int eDVBServicePlay::selectAudioStream(int i) { eDVBServicePMTHandler::program program; eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; + pts_t position = -1; if (h.getProgramInfo(program)) return -1; @@ -1765,6 +1766,9 @@ int eDVBServicePlay::selectAudioStream(int i) apidtype = program.audioStreams[stream].type; } + if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active)) + eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position); + m_current_audio_pid = apid; if (m_is_primary && m_decoder->setAudioPID(apid, apidtype)) @@ -1773,6 +1777,9 @@ int eDVBServicePlay::selectAudioStream(int i) return -4; } + if (position != -1) + eDebug("seekTo ret %d", seekTo(position)); + int rdsPid = apid; /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */ -- cgit v1.2.3 From bbe28d433549d0559ac2f91ca2903d5bc6b60bf4 Mon Sep 17 00:00:00 2001 From: ghost Date: Wed, 9 Dec 2009 15:47:56 +0100 Subject: fix skip backward from live to timeshift --- lib/python/Screens/InfoBarGenerics.py | 3 --- lib/service/servicedvb.cpp | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 39a8b59d..527b9772 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -1205,10 +1205,7 @@ class InfoBarTimeshift: self.setSeekState(self.SEEK_STATE_PAUSE) if back: - self.doSeek(-5) # seek some gops before end self.ts_rewind_timer.start(200, 1) - else: - self.doSeek(-1) # seek 1 gop before end def rewindService(self): self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value))) diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index b71271a9..9a995e7b 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -2285,12 +2285,13 @@ void eDVBServicePlay::switchToTimeshift() r.path = m_timeshift_file; m_cue = new eCueSheet(); + m_cue->seekTo(0, -1000); m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */ eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now."); pause(); updateDecoder(); /* mainly to switch off PCR, and to set pause */ - + m_event((iPlayableService*)this, evSeekableStatusChanged); } -- cgit v1.2.3