Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #2955 from popcornmix/ff_rew

[rtbp/omxplayer] Support ff/rew
  • Loading branch information...
commit dde99fbd7a4abceb7598f3819db9e8af5be29544 2 parents e5cd6a3 + 4fddb9a
popcornmix popcornmix authored
58 xbmc/cores/omxplayer/OMXPlayer.cpp
View
@@ -120,6 +120,11 @@
#include "LangInfo.h"
#include "URL.h"
+// video not playing from clock, but stepped
+#define TP(speed) ((speed) < 0 || (speed) > 4*DVD_PLAYSPEED_NORMAL)
+// audio not playing
+#define TPA(speed) ((speed) != DVD_PLAYSPEED_PAUSE && (speed) != DVD_PLAYSPEED_NORMAL)
+
using namespace std;
using namespace PVR;
@@ -1164,7 +1169,24 @@ void COMXPlayer::Process()
m_omxPlayerAudio.GetLevel(), m_omxPlayerVideo.GetLevel(), m_omxPlayerAudio.GetDelay(), (float)m_omxPlayerAudio.GetCacheTotal());
#endif
- if (not_accepts_data && (audio_fifo_low || video_fifo_low))
+ if (TP(m_playSpeed))
+ {
+ if (m_CurrentVideo.started)
+ {
+ static double last = 0;
+ double now = m_clock.GetAbsoluteClock();
+ //if (m_av_clock.OMXIsPaused())
+ // m_av_clock.OMXResume();
+ if (m_clock.GetAbsoluteClock() - last > 1e6/25)
+ {
+ // trickplay modes progress by stepping
+ //m_av_clock.OMXMediaTime(m_clock.GetClock());
+ m_av_clock.OMXStep();
+ last = now;
+ }
+ }
+ }
+ else if (not_accepts_data && (audio_fifo_low || video_fifo_low))
{
CLog::Log(LOGDEBUG, "%s - Flush! M:%.6f-%.6f (A:%.6f V:%.6f) PEF:%d%d%d S:%.2f A:%.2f V:%.2f/T:%.2f (A:%d%d V:%d%d) A:%d%% V:%d%% (%.2f,%.2f)", __FUNCTION__,
stamp*1e-6, m_av_clock.OMXClockAdjustment()*1e-6, audio_pts*1e-6, video_pts*1e-6, m_av_clock.OMXIsPaused(), bOmxSentEOFs, not_accepts_data, m_playSpeed * (1.0f/DVD_PLAYSPEED_NORMAL),
@@ -2429,10 +2451,18 @@ void COMXPlayer::HandleMessages()
// videoplayer just plays faster after the clock speed has been increased
// 1. disable audio
// 2. skip frames and adjust their pts or the clock
+
+ // when switching from trickplay to normal, we may not have a full set of reference frames
+ // in decoder and we may get corrupt frames out. Seeking to current time will avoid this.
+ if ( (speed == DVD_PLAYSPEED_PAUSE || speed == DVD_PLAYSPEED_NORMAL) &&
+ (m_playSpeed != DVD_PLAYSPEED_PAUSE && m_playSpeed != DVD_PLAYSPEED_NORMAL) )
+ m_messenger.Put(new CDVDMsgPlayerSeek(DVD_TIME_TO_MSEC(m_clock.GetClock()), (speed < 0), true, false, false, true));
+
m_playSpeed = speed;
m_caching = CACHESTATE_DONE;
m_clock.SetSpeed(speed);
m_av_clock.OMXSetSpeed(speed);
+ m_av_clock.OMXPause();
m_omxPlayerAudio.SetSpeed(speed);
m_omxPlayerVideo.SetSpeed(speed);
@@ -2520,12 +2550,15 @@ void COMXPlayer::HandleMessages()
if(player == DVDPLAYER_VIDEO)
m_CurrentVideo.started = true;
- if ((player == DVDPLAYER_AUDIO || player == DVDPLAYER_VIDEO) && (!m_HasAudio || m_CurrentAudio.started) && (!m_HasVideo || m_CurrentVideo.started))
+ if ((player == DVDPLAYER_AUDIO || player == DVDPLAYER_VIDEO) &&
+ (TPA(m_playSpeed) || !m_HasAudio || m_CurrentAudio.started) &&
+ (!m_HasVideo || m_CurrentVideo.started))
{
- m_av_clock.OMXReset(m_HasVideo, m_HasAudio);
+ CLog::Log(LOGDEBUG, "COMXPlayer::HandleMessages - player started RESET");
+ m_av_clock.OMXReset(m_HasVideo, m_playSpeed != DVD_PLAYSPEED_NORMAL && m_playSpeed != DVD_PLAYSPEED_PAUSE ? false:m_HasAudio);
}
- CLog::Log(LOGDEBUG, "COMXPlayer::HandleMessages - player started %d", player);
+ CLog::Log(LOGDEBUG, "COMXPlayer::HandleMessages - player started %d (tpa:%d,a:%d,v:%d)", player, TPA(m_playSpeed), m_CurrentAudio.started, m_CurrentVideo.started);
}
else if (pMsg->IsType(CDVDMsg::PLAYER_DISPLAYTIME))
{
@@ -2576,7 +2609,7 @@ void COMXPlayer::SetCaching(ECacheState state)
|| state == CACHESTATE_PVR)
{
m_clock.SetSpeed(DVD_PLAYSPEED_PAUSE);
- m_av_clock.OMXSetSpeed(DVD_PLAYSPEED_PAUSE);
+ m_av_clock.OMXPause();
m_omxPlayerAudio.SetSpeed(DVD_PLAYSPEED_PAUSE);
m_omxPlayerAudio.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1);
m_omxPlayerVideo.SetSpeed(DVD_PLAYSPEED_PAUSE);
@@ -2590,7 +2623,6 @@ void COMXPlayer::SetCaching(ECacheState state)
||(state == CACHESTATE_DONE && m_caching != CACHESTATE_PLAY))
{
m_clock.SetSpeed(m_playSpeed);
- m_av_clock.OMXSetSpeed(m_playSpeed);
m_omxPlayerAudio.SetSpeed(m_playSpeed);
m_omxPlayerVideo.SetSpeed(m_playSpeed);
m_pInputStream->ResetScanTimeout(0);
@@ -2600,10 +2632,6 @@ void COMXPlayer::SetCaching(ECacheState state)
void COMXPlayer::SetPlaySpeed(int speed)
{
- /* only pause and normal playspeeds are allowed */
- if(speed < 0 || speed > DVD_PLAYSPEED_NORMAL)
- return;
-
m_messenger.Put(new CDVDMsgInt(CDVDMsg::PLAYER_SETSPEED, speed));
m_omxPlayerAudio.SetSpeed(speed);
m_omxPlayerVideo.SetSpeed(speed);
@@ -3014,6 +3042,8 @@ int64_t COMXPlayer::GetTime()
if(offset < -limit) offset = -limit;
}
//{CLog::Log(LOGINFO, "%s: time:%.2f stamp:%.2f dts:%d m:%d (p:%d,c:%d) =%llu", __func__, (double)m_State.time, (double)m_State.timestamp, (int)DVD_TIME_TO_MSEC(m_State.dts + m_offset_pts), (int)DVD_TIME_TO_MSEC(m_av_clock.OMXMediaTime()), (int)m_playSpeed, (int)m_caching, llrint(m_State.time + DVD_TIME_TO_MSEC(offset)));}
+ if (TP(m_playSpeed))
+ return DVD_TIME_TO_MSEC(m_clock.GetClock());
return llrint(m_State.time + DVD_TIME_TO_MSEC(offset));
}
@@ -3035,11 +3065,6 @@ void COMXPlayer::ToFFRW(int iSpeed)
// can't rewind in menu as seeking isn't possible
// forward is fine
if (iSpeed < 0 && IsInMenu()) return;
-
- /* only pause and normal playspeeds are allowed */
- if(iSpeed > 1 || iSpeed < 0)
- return;
-
SetPlaySpeed(iSpeed * DVD_PLAYSPEED_NORMAL);
}
@@ -3415,7 +3440,8 @@ void COMXPlayer::FlushBuffers(bool queued, double pts, bool accurate)
CLog::Log(LOGNOTICE, "FlushBuffers: q:%d pts:%.0f a:%d", queued, pts, accurate);
- m_av_clock.OMXStop();
+ if (!TP(m_playSpeed))
+ m_av_clock.OMXStop();
m_av_clock.OMXPause();
if(accurate)
7 xbmc/cores/omxplayer/OMXPlayerAudio.cpp
View
@@ -226,7 +226,7 @@ bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket)
const uint8_t *data_dec = pkt->pData;
int data_len = pkt->iSize;
- if(!OMX_IS_RAW(m_format.m_dataFormat))
+ if(!OMX_IS_RAW(m_format.m_dataFormat) && !bDropPacket)
{
while(!m_bStop && data_len > 0)
{
@@ -283,15 +283,12 @@ bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket)
}
}
- int n = (m_nChannels * m_hints.bitspersample * m_hints.samplerate)>>3;
- if (n > 0)
- m_audioClock += ((double)decoded_size * DVD_TIME_BASE) / n;
break;
}
}
}
- else
+ else if(!bDropPacket)
{
if(CodecChange())
{
41 xbmc/linux/OMXClock.cpp
View
@@ -33,6 +33,7 @@
#include "utils/MathUtils.h"
#define OMX_PRE_ROLL 200
+#define TP(speed) ((speed) < 0 || (speed) > 4*DVD_PLAYSPEED_NORMAL)
OMXClock::OMXClock()
{
@@ -40,7 +41,9 @@ OMXClock::OMXClock()
m_fps = 25.0f;
m_omx_speed = DVD_PLAYSPEED_NORMAL;
- m_eClock = OMX_TIME_RefClockMax;
+ m_WaitMask = 0;
+ m_eState = OMX_TIME_ClockStateStopped;
+ m_eClock = OMX_TIME_RefClockNone;
m_clock = NULL;
pthread_mutex_init(&m_lock, NULL);
@@ -222,6 +225,7 @@ bool OMXClock::OMXStop(bool lock /* = true */)
UnLock();
return false;
}
+ m_eState = clock.eState;
if(lock)
UnLock();
@@ -256,6 +260,7 @@ bool OMXClock::OMXStep(int steps /* = 1 */, bool lock /* = true */)
if(lock)
UnLock();
+ CLog::Log(LOGDEBUG, "OMXClock::Step (%d)", steps);
return true;
}
@@ -267,8 +272,6 @@ bool OMXClock::OMXReset(bool has_video, bool has_audio, bool lock /* = true */)
if(lock)
Lock();
- OMX_ERRORTYPE omx_err = OMX_ErrorNone;
-
if(!OMXSetReferenceClock(has_audio, false))
{
if(lock)
@@ -276,21 +279,11 @@ bool OMXClock::OMXReset(bool has_video, bool has_audio, bool lock /* = true */)
return false;
}
- OMX_TIME_CONFIG_CLOCKSTATETYPE clock;
- OMX_INIT_STRUCTURE(clock);
-
- omx_err = m_omx_clock.GetConfig(OMX_IndexConfigTimeClockState, &clock);
- if(omx_err != OMX_ErrorNone)
+ if (m_eState == OMX_TIME_ClockStateStopped)
{
- CLog::Log(LOGERROR, "OMXClock::OMXReset error getting OMX_IndexConfigTimeClockState\n");
- if(lock)
- UnLock();
- return false;
- }
+ OMX_TIME_CONFIG_CLOCKSTATETYPE clock;
+ OMX_INIT_STRUCTURE(clock);
- OMX_TIME_CLOCKSTATE old_eState = clock.eState;
- if (clock.eState == OMX_TIME_ClockStateStopped)
- {
clock.eState = OMX_TIME_ClockStateWaitingForStartTime;
clock.nOffset = ToOMXTime(-1000LL * OMX_PRE_ROLL);
@@ -298,7 +291,7 @@ bool OMXClock::OMXReset(bool has_video, bool has_audio, bool lock /* = true */)
if(clock.nWaitMask)
{
- omx_err = m_omx_clock.SetConfig(OMX_IndexConfigTimeClockState, &clock);
+ OMX_ERRORTYPE omx_err = m_omx_clock.SetConfig(OMX_IndexConfigTimeClockState, &clock);
if(omx_err != OMX_ErrorNone)
{
CLog::Log(LOGERROR, "OMXClock::OMXReset error setting OMX_IndexConfigTimeClockState\n");
@@ -306,10 +299,13 @@ bool OMXClock::OMXReset(bool has_video, bool has_audio, bool lock /* = true */)
UnLock();
return false;
}
+ CLog::Log(LOGDEBUG, "OMXClock::OMXReset audio / video : %d / %d wait mask %d->%d state : %d->%d\n",
+ has_audio, has_video, m_WaitMask, clock.nWaitMask, m_eState, clock.eState);
+ if (m_eState != OMX_TIME_ClockStateStopped)
+ m_WaitMask = clock.nWaitMask;
+ m_eState = clock.eState;
}
}
- CLog::Log(LOGDEBUG, "OMXClock::OMXReset audio / video : %d / %d wait mask %d state : %d->%d\n",
- has_audio, has_video, clock.nWaitMask, old_eState, clock.eState);
if(lock)
UnLock();
@@ -453,7 +449,7 @@ bool OMXClock::OMXResume(bool lock /* = true */)
if(lock)
Lock();
- if (OMXSetSpeed(DVD_PLAYSPEED_NORMAL, false, true))
+ if (OMXSetSpeed(m_omx_speed, false, true))
m_pause = false;
if(lock)
@@ -478,7 +474,10 @@ bool OMXClock::OMXSetSpeed(int speed, bool lock /* = true */, bool pause_resume
OMX_TIME_CONFIG_SCALETYPE scaleType;
OMX_INIT_STRUCTURE(scaleType);
- scaleType.xScale = (speed << 16) / DVD_PLAYSPEED_NORMAL;
+ if (TP(speed))
+ scaleType.xScale = 0; // for trickplay we just pause, and single step
+ else
+ scaleType.xScale = (speed << 16) / DVD_PLAYSPEED_NORMAL;
omx_err = m_omx_clock.SetConfig(OMX_IndexConfigTimeScale, &scaleType);
if(omx_err != OMX_ErrorNone)
{
2  xbmc/linux/OMXClock.h
View
@@ -52,6 +52,8 @@ class OMXClock
pthread_mutex_t m_lock;
double m_fps;
int m_omx_speed;
+ OMX_U32 m_WaitMask;
+ OMX_TIME_CLOCKSTATE m_eState;
OMX_TIME_REFCLOCKTYPE m_eClock;
CDVDClock *m_clock;
private:
Please sign in to comment.
Something went wrong with that request. Please try again.