aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFelix Domke <tmbinc@elitedvb.net>2008-11-18 00:40:19 +0100
committerFelix Domke <tmbinc@elitedvb.net>2008-11-18 00:40:19 +0100
commit4f7990ff2a55874b9eb65e3c9cd47dacb9f76deb (patch)
tree47ebc002512c74a06eb08c5b6739d24c7c4443ed /lib
parent3aedbe22cf74b72ad0c3e2bc1869e914701e6574 (diff)
downloadenigma2-4f7990ff2a55874b9eb65e3c9cd47dacb9f76deb.tar.gz
enigma2-4f7990ff2a55874b9eb65e3c9cd47dacb9f76deb.zip
rework decoder states
Diffstat (limited to 'lib')
-rw-r--r--lib/dvb/decoder.cpp208
-rw-r--r--lib/dvb/decoder.h42
-rw-r--r--lib/dvb/idvb.h33
-rw-r--r--lib/python/Screens/InfoBarGenerics.py17
-rw-r--r--lib/service/iservice.h2
-rw-r--r--lib/service/servicedvb.cpp40
-rw-r--r--lib/service/servicedvb.h1
7 files changed, 177 insertions, 166 deletions
diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp
index 6ad39225..66b923a6 100644
--- a/lib/dvb/decoder.cpp
+++ b/lib/dvb/decoder.cpp
@@ -39,7 +39,7 @@
DEFINE_REF(eDVBAudio);
eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev)
- :m_demux(demux), m_dev(dev), m_is_freezed(0)
+ :m_demux(demux), m_dev(dev)
{
char filename[128];
#if HAVE_DVB_API_VERSION < 3
@@ -194,7 +194,7 @@ int eDVBAudio::startPid(int pid, int type)
*/
}
- eDebugNoNewLine("AUDIO_SET_BYPASS - ");
+ eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass);
if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
eDebug("failed (%m)");
else
@@ -240,28 +240,20 @@ void eDVBAudio::flush()
void eDVBAudio::freeze()
{
- if (!m_is_freezed)
- {
- eDebugNoNewLine("AUDIO_PAUSE - ");
- if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
- eDebug("failed (%m)");
- else
- eDebug("ok");
- m_is_freezed=1;
- }
+ eDebugNoNewLine("AUDIO_PAUSE - ");
+ if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
+ eDebug("failed (%m)");
+ else
+ eDebug("ok");
}
void eDVBAudio::unfreeze()
{
- if (m_is_freezed)
- {
- eDebugNoNewLine("AUDIO_CONTINUE - ");
- if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
- eDebug("failed (%m)");
- else
- eDebug("ok");
- m_is_freezed=0;
- }
+ eDebugNoNewLine("AUDIO_CONTINUE - ");
+ if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
+ eDebug("failed (%m)");
+ else
+ eDebug("ok");
}
void eDVBAudio::setChannel(int channel)
@@ -299,7 +291,7 @@ eDVBAudio::~eDVBAudio()
DEFINE_REF(eDVBVideo);
eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev)
- :m_demux(demux), m_dev(dev), m_is_slow_motion(0), m_is_fast_forward(0), m_is_freezed(0)
+ :m_demux(demux), m_dev(dev)
{
char filename[128];
#if HAVE_DVB_API_VERSION < 3
@@ -461,34 +453,25 @@ void eDVBVideo::flush()
void eDVBVideo::freeze()
{
- if (!m_is_freezed)
- {
- eDebugNoNewLine("VIDEO_FREEZE - ");
- if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
- eDebug("failed (%m)");
- else
- eDebug("ok");
- m_is_freezed=1;
- }
+ eDebugNoNewLine("VIDEO_FREEZE - ");
+ if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
+ eDebug("failed (%m)");
+ else
+ eDebug("ok");
}
void eDVBVideo::unfreeze()
{
- if (m_is_freezed)
- {
- eDebugNoNewLine("VIDEO_CONTINUE - ");
- if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
- eDebug("failed (%m)");
- else
- eDebug("ok");
- m_is_freezed=0;
- }
+ eDebugNoNewLine("VIDEO_CONTINUE - ");
+ if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
+ eDebug("failed (%m)");
+ else
+ eDebug("ok");
}
int eDVBVideo::setSlowMotion(int repeat)
{
- eDebugNoNewLine("VIDEO_SLOWMOTION - ");
- m_is_slow_motion = repeat;
+ eDebugNoNewLine("VIDEO_SLOWMOTION(%d) - ", repeat);
int ret = ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat);
if (ret < 0)
eDebug("failed(%m)");
@@ -499,8 +482,7 @@ int eDVBVideo::setSlowMotion(int repeat)
int eDVBVideo::setFastForward(int skip)
{
- eDebugNoNewLine("VIDEO_FAST_FORWARD - ");
- m_is_fast_forward = skip;
+ eDebugNoNewLine("VIDEO_FAST_FORWARD(%d) - ", skip);
int ret = ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip);
if (ret < 0)
eDebug("failed(%m)");
@@ -527,11 +509,6 @@ int eDVBVideo::getPTS(pts_t &now)
eDVBVideo::~eDVBVideo()
{
- if (m_is_slow_motion)
- setSlowMotion(0);
- if (m_is_fast_forward)
- setFastForward(0);
- unfreeze();
if (m_fd >= 0)
::close(m_fd);
if (m_fd_demux >= 0)
@@ -750,14 +727,14 @@ int eTSMPEGDecoder::setState()
{
int res = 0;
- int noaudio = m_is_sm || m_is_ff || m_is_trickmode;
+ int noaudio = (m_state != statePlay) && (m_state != statePause);
int nott = noaudio; /* actually same conditions */
if ((noaudio && m_audio) || (!m_audio && !noaudio))
- m_changed |= changeAudio;
+ m_changed |= changeAudio | changeState;
if ((nott && m_text) || (!m_text && !nott))
- m_changed |= changeText;
+ m_changed |= changeText | changeState;
bool changed = !!m_changed;
#if HAVE_DVB_API_VERSION < 3
@@ -900,6 +877,39 @@ int eTSMPEGDecoder::setState()
m_changed &= ~changeText;
}
#endif
+
+ if (m_changed & changeState)
+ {
+ /* play, slowmotion, fast-forward */
+ int state_table[6][4] =
+ {
+ /* [stateStop] = */ {0, 0, 0},
+ /* [statePause] = */ {0, 0, 0},
+ /* [statePlay] = */ {1, 0, 0},
+ /* [stateDecoderFastForward] = */ {1, 0, m_ff_sm_ratio},
+ /* [stateHighspeedFastForward] = */ {1, 0, 1},
+ /* [stateSlowMotion] = */ {1, m_ff_sm_ratio, 0}
+ };
+ int *s = state_table[m_state];
+ if (m_video)
+ {
+ m_video->setSlowMotion(s[1]);
+ m_video->setFastForward(s[2]);
+ if (s[0])
+ m_video->unfreeze();
+ else
+ m_video->freeze();
+ }
+ if (m_audio)
+ {
+ if (s[0])
+ m_audio->unfreeze();
+ else
+ m_audio->freeze();
+ }
+ m_changed &= ~changeState;
+ }
+
if (changed && !m_video && m_audio && m_radio_pic.length())
showSinglePic(m_radio_pic.c_str());
@@ -946,7 +956,7 @@ eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder)
{
demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn);
CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic);
- m_is_ff = m_is_sm = m_is_trickmode = 0;
+ m_state = stateStop;
}
eTSMPEGDecoder::~eTSMPEGDecoder()
@@ -1028,82 +1038,61 @@ RESULT eTSMPEGDecoder::setSyncMaster(int who)
return -1;
}
-RESULT eTSMPEGDecoder::start()
-{
- RESULT r;
- r = setState();
- if (r)
- return r;
- return unfreeze();
-}
-
- /* preroll is start in freezed mode. */
-RESULT eTSMPEGDecoder::preroll()
+RESULT eTSMPEGDecoder::set()
{
return setState();
}
-RESULT eTSMPEGDecoder::freeze(int cont)
-{
- if (m_video)
- m_video->freeze();
-
- if (m_audio)
- m_audio->freeze();
-
- return 0;
-}
-
-RESULT eTSMPEGDecoder::unfreeze()
-{
- if (m_video)
- m_video->unfreeze();
-
- if (m_audio)
- m_audio->unfreeze();
-
- return 0;
-}
-
-RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
+RESULT eTSMPEGDecoder::play()
{
- return -1;
+ if (m_state == statePlay)
+ return 0;
+ m_state = statePlay;
+ m_changed |= changeState;
+ return setState();
}
-RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
+RESULT eTSMPEGDecoder::pause()
{
- return -1;
+ if (m_state == statePause)
+ return 0;
+ m_state = statePause;
+ m_changed |= changeState;
+ return setState();
}
RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
{
- m_is_ff = frames_to_skip != 0;
+ if ((m_state == stateDecoderFastForward) && (m_ff_sm_ratio == frames_to_skip))
+ return 0;
- setState();
- unfreeze(); // audio might be restarted and still in preroll (freezed) state.
+ m_state = stateDecoderFastForward;
+ m_ff_sm_ratio = frames_to_skip;
+ m_changed |= changeState;
+ return setState();
- if (m_video)
- return m_video->setFastForward(frames_to_skip);
- else
- return -1;
+// return m_video->setFastForward(frames_to_skip);
}
RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
{
- m_is_sm = repeat != 0;
+ if ((m_state == stateSlowMotion) && (m_ff_sm_ratio == repeat))
+ return 0;
- setState();
- unfreeze(); // audio might be restarted and still in preroll (freezed) state.
-
- if (m_video)
- return m_video->setSlowMotion(repeat);
- else
- return -1;
+ m_state = stateSlowMotion;
+ m_ff_sm_ratio = repeat;
+ m_changed |= changeState;
+ return setState();
}
-RESULT eTSMPEGDecoder::setZoom(int what)
+RESULT eTSMPEGDecoder::setTrickmode()
{
- return -1;
+ if (m_state == stateTrickmode)
+ return 0;
+
+ m_state = stateTrickmode;
+ m_changed |= changeState;
+ return setState();
}
RESULT eTSMPEGDecoder::flush()
@@ -1127,13 +1116,6 @@ void eTSMPEGDecoder::demux_event(int event)
}
}
-RESULT eTSMPEGDecoder::setTrickmode(int what)
-{
- m_is_trickmode = what;
- setState();
- return 0;
-}
-
RESULT eTSMPEGDecoder::getPTS(int what, pts_t &pts)
{
if (what == 0) /* auto */
diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h
index 05e07ef9..04501fe6 100644
--- a/lib/dvb/decoder.h
+++ b/lib/dvb/decoder.h
@@ -119,10 +119,12 @@ private:
changeVideo = 1,
changeAudio = 2,
changePCR = 4,
- changeText = 8
+ changeText = 8,
+ changeState = 16,
};
int m_changed, m_decoder;
- int m_is_ff, m_is_sm, m_is_trickmode;
+ int m_state;
+ int m_ff_sm_ratio;
int setState();
ePtr<eConnection> m_demux_event_conn;
ePtr<eConnection> m_video_event_conn;
@@ -148,17 +150,33 @@ public:
RESULT setSyncPCR(int pcrpid);
RESULT setTextPID(int textpid);
RESULT setSyncMaster(int who);
- RESULT start();
- RESULT preroll();
- RESULT freeze(int cont);
- RESULT unfreeze();
- RESULT setSinglePictureMode(int when);
- RESULT setPictureSkipMode(int what);
- RESULT setFastForward(int frames_to_skip);
- RESULT setSlowMotion(int repeat);
- RESULT setZoom(int what);
+
+ /*
+ The following states exist:
+
+ - stop: data source closed, no playback
+ - pause: data source active, decoder paused
+ - play: data source active, decoder consuming
+ - decoder fast forward: data source linear, decoder drops frames
+ - trickmode, highspeed reverse: data source fast forwards / reverses, decoder just displays frames as fast as it can
+ - slow motion: decoder displays frames multiple times
+ */
+ enum {
+ stateStop,
+ statePause,
+ statePlay,
+ stateDecoderFastForward,
+ stateTrickmode,
+ stateSlowMotion
+ };
+ RESULT set(); /* just apply settings, keep state */
+ RESULT play(); /* -> play */
+ RESULT pause(); /* -> pause */
+ RESULT setFastForward(int frames_to_skip); /* -> decoder fast forward */
+ RESULT setSlowMotion(int repeat); /* -> slow motion **/
+ RESULT setTrickmode(); /* -> highspeed fast forward */
+
RESULT flush();
- RESULT setTrickmode(int what);
RESULT showSinglePic(const char *filename);
RESULT setRadioPic(const std::string &filename);
/* what 0=auto, 1=video, 2=audio. */
diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h
index cda05894..bd1c7035 100644
--- a/lib/dvb/idvb.h
+++ b/lib/dvb/idvb.h
@@ -662,37 +662,24 @@ public:
/** Set Sync mode to either audio or video master */
virtual RESULT setSyncMaster(int who)=0;
- /** Apply settings with starting video */
- virtual RESULT start()=0;
- /** Apply settings but don't start yet */
- virtual RESULT preroll()=0;
+ /** Apply settings but don't change state */
+ virtual RESULT set()=0;
+ /* all those apply settings, then transition to the given state */
- /** Freeze frame. Either continue decoding (without display) or halt. */
- virtual RESULT freeze(int cont)=0;
- /** Continue after freeze. */
- virtual RESULT unfreeze()=0;
+ /** play */
+ virtual RESULT play()=0;
+ /** Freeze frame. */
+ virtual RESULT pause()=0;
/** fast forward by skipping frames. 0 is disabled, 2 is twice-the-speed, ... */
virtual RESULT setFastForward(int skip=0)=0;
- // stop on .. Picture
- enum { spm_I, spm_Ref, spm_Any };
- /** Stop on specific decoded picture. For I-Frame display. */
- virtual RESULT setSinglePictureMode(int when)=0;
-
- enum { pkm_B, pkm_PB };
- /** Fast forward by skipping either B or P/B pictures */
- virtual RESULT setPictureSkipMode(int what)=0;
-
/** Slow Motion by repeating pictures */
virtual RESULT setSlowMotion(int repeat)=0;
-
- enum { zoom_Normal, zoom_PanScan, zoom_Letterbox, zoom_Fullscreen };
- /** Set Zoom. mode *must* be fitting. */
- virtual RESULT setZoom(int what)=0;
-
- virtual RESULT setTrickmode(int what) = 0;
+ /** Display any complete data as fast as possible */
+ virtual RESULT setTrickmode()=0;
+
virtual RESULT getPTS(int what, pts_t &pts) = 0;
virtual RESULT showSinglePic(const char *filename) = 0;
diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py
index cdaa2c1e..409018de 100644
--- a/lib/python/Screens/InfoBarGenerics.py
+++ b/lib/python/Screens/InfoBarGenerics.py
@@ -779,12 +779,21 @@ class InfoBarSeek:
print "not pauseable."
state = self.SEEK_STATE_PLAY
- oldstate = self.seekstate
self.seekstate = state
- for i in range(3):
- if oldstate[i] != self.seekstate[i]:
- (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
+ if pauseable is not None:
+ if self.seekstate[0]:
+ print "resolved to PAUSE"
+ pauseable.pause()
+ elif self.seekstate[1]:
+ print "resolved to FAST FORWARD"
+ pauseable.setFastForward(self.seekstate[1])
+ elif self.seekstate[2]:
+ print "resolved to SLOW MOTION"
+ pauseable.setSlowMotion(self.seekstate[2])
+ else:
+ print "resolved to PLAY"
+ pauseable.unpause()
for c in self.onPlayStateChanged:
c(self.seekstate)
diff --git a/lib/service/iservice.h b/lib/service/iservice.h
index 02fc4508..e27752a2 100644
--- a/lib/service/iservice.h
+++ b/lib/service/iservice.h
@@ -392,6 +392,8 @@ class iPauseableService: public iObject
~iPausableService();
#endif
public:
+
+ /* this will set the *state* directly. So just call a SINGLE function of those at a time. */
virtual RESULT pause()=0;
virtual RESULT unpause()=0;
diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp
index 7e6c0337..af3ab206 100644
--- a/lib/service/servicedvb.cpp
+++ b/lib/service/servicedvb.cpp
@@ -1281,7 +1281,9 @@ RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
RESULT eDVBServicePlay::setSlowMotion(int ratio)
{
+ assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
+ setFastForward_internal(0);
if (m_decoder)
return m_decoder->setSlowMotion(ratio);
else
@@ -1291,6 +1293,12 @@ RESULT eDVBServicePlay::setSlowMotion(int ratio)
RESULT eDVBServicePlay::setFastForward(int ratio)
{
eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
+ assert(ratio);
+ return setFastForward_internal(ratio);
+}
+
+RESULT eDVBServicePlay::setFastForward_internal(int ratio)
+{
int skipmode, ffratio;
if (ratio > 8)
@@ -1323,7 +1331,12 @@ RESULT eDVBServicePlay::setFastForward(int ratio)
if (!m_decoder)
return -1;
- return m_decoder->setFastForward(ffratio);
+ if (ffratio == 0)
+ return 0;
+ else if (ffratio != 1)
+ return m_decoder->setFastForward(ffratio);
+ else
+ return m_decoder->setTrickmode();
}
RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
@@ -1352,10 +1365,10 @@ RESULT eDVBServicePlay::getLength(pts_t &len)
RESULT eDVBServicePlay::pause()
{
eDebug("eDVBServicePlay::pause");
- if (!m_is_paused && m_decoder)
+ setFastForward_internal(0);
+ if (m_decoder)
{
- m_is_paused = 1;
- return m_decoder->freeze(0);
+ return m_decoder->pause();
} else
return -1;
}
@@ -1363,10 +1376,10 @@ RESULT eDVBServicePlay::pause()
RESULT eDVBServicePlay::unpause()
{
eDebug("eDVBServicePlay::unpause");
- if (m_is_paused && m_decoder)
+ setFastForward_internal(0);
+ if (m_decoder)
{
- m_is_paused = 0;
- return m_decoder->unfreeze();
+ return m_decoder->play();
} else
return -1;
}
@@ -1448,9 +1461,8 @@ RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
RESULT eDVBServicePlay::setTrickmode(int trick)
{
- if (m_decoder)
- m_decoder->setTrickmode(trick);
- return 0;
+ /* currently unimplemented */
+ return -1;
}
RESULT eDVBServicePlay::isCurrentlySeekable()
@@ -1761,7 +1773,7 @@ RESULT eDVBServicePlay::selectTrack(unsigned int i)
{
int ret = selectAudioStream(i);
- if (m_decoder->start())
+ if (m_decoder->play())
return -5;
return ret;
@@ -2486,12 +2498,12 @@ void eDVBServicePlay::updateDecoder()
m_teletext_parser->start(program.textPid);
if (!m_is_primary)
- m_decoder->setTrickmode(1);
+ m_decoder->setTrickmode();
if (m_is_paused)
- m_decoder->preroll();
+ m_decoder->pause();
else
- m_decoder->start();
+ m_decoder->play();
if (vpid > 0 && vpid < 0x2000)
;
diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h
index d19b92d6..c19e1ed5 100644
--- a/lib/service/servicedvb.h
+++ b/lib/service/servicedvb.h
@@ -218,6 +218,7 @@ private:
int m_current_audio_stream;
int selectAudioStream(int n = -1);
+ RESULT setFastForward_internal(int ratio);
/* timeshift */
ePtr<iDVBTSRecorder> m_record;