Skip to content

Commit

Permalink
dvdplayer: more ff/rw fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
FernetMenta authored and popcornmix committed May 16, 2015
1 parent eb398c2 commit 977976f
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 49 deletions.
102 changes: 59 additions & 43 deletions xbmc/cores/dvdplayer/DVDPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1876,50 +1876,65 @@ void CDVDPlayer::HandlePlaySpeed()
SetPlaySpeed(DVD_PLAYSPEED_NORMAL);

}
else if (m_CurrentVideo.id >= 0
&& (m_CurrentVideo.inited == true || GetPlaySpeed() < 0) // allow rewind at end of file
&& (m_SpeedState.lastpts != m_dvdPlayerVideo->GetCurrentPts() || fabs(m_SpeedState.lastabstime - CDVDClock::GetAbsoluteClock()) > DVD_MSEC_TO_TIME(200))
&& (m_dvdPlayerVideo->GetCurrentPts() != DVD_NOPTS_VALUE)
&& m_SpeedState.lasttime != GetTime())
else
{
m_SpeedState.lastpts = m_dvdPlayerVideo->GetCurrentPts();
m_SpeedState.lasttime = GetTime();
m_SpeedState.lastabstime = CDVDClock::GetAbsoluteClock();
// check how much off clock video is when ff/rw:ing
// a problem here is that seeking isn't very accurate
// and since the clock will be resynced after seek
// we might actually not really be playing at the wanted
// speed. we'd need to have some way to not resync the clock
// after a seek to remember timing. still need to handle
// discontinuities somehow

// when seeking, give the player a headstart to make sure
// the time it takes to seek doesn't make a difference.
double error;
error = m_clock.GetClock() - m_SpeedState.lastpts;
error *= m_playSpeed / abs(m_playSpeed);

// allow a bigger error when going ff, the faster we go
// the the bigger is the error we allow
if (m_playSpeed > DVD_PLAYSPEED_NORMAL)
bool check = true;

// only check if we have video
if (m_CurrentVideo.id < 0 || !m_CurrentVideo.started)
check = false;
// video message queue either initiated or already seen eof
else if (m_CurrentVideo.inited == false && m_playSpeed >= 0)
check = false;
// don't check if time has not advanced since last check
else if (m_SpeedState.lasttime == GetTime())
check = false;
// skip if frame at screen has no valid timestamp
else if (m_dvdPlayerVideo->GetCurrentPts() == DVD_NOPTS_VALUE)
check = false;
// skip if frame on screen has not changed
else if (m_SpeedState.lastpts == m_dvdPlayerVideo->GetCurrentPts() &&
fabs(m_SpeedState.lastabstime - CDVDClock::GetAbsoluteClock()) < DVD_MSEC_TO_TIME(1000))
check = false;

if (check)
{
int errorwin = m_playSpeed / DVD_PLAYSPEED_NORMAL;
if (errorwin > 8)
errorwin = 8;
error /= errorwin;
}

if(error > DVD_MSEC_TO_TIME(1000))
{
error = (int)DVD_TIME_TO_MSEC(m_clock.GetClock()) - m_SpeedState.lastseekpts;
m_SpeedState.lastpts = m_dvdPlayerVideo->GetCurrentPts();
m_SpeedState.lasttime = GetTime();
m_SpeedState.lastabstime = CDVDClock::GetAbsoluteClock();
// check how much off clock video is when ff/rw:ing
// a problem here is that seeking isn't very accurate
// and since the clock will be resynced after seek
// we might actually not really be playing at the wanted
// speed. we'd need to have some way to not resync the clock
// after a seek to remember timing. still need to handle
// discontinuities somehow

double error;
error = m_clock.GetClock() - m_SpeedState.lastpts;
error *= m_playSpeed / abs(m_playSpeed);

// allow a bigger error when going ff, the faster we go
// the the bigger is the error we allow
if (m_playSpeed > DVD_PLAYSPEED_NORMAL)
{
int errorwin = m_playSpeed / DVD_PLAYSPEED_NORMAL;
if (errorwin > 8)
errorwin = 8;
error /= errorwin;
}

if(abs(error) > 1000)
if(error > DVD_MSEC_TO_TIME(1000))
{
CLog::Log(LOGDEBUG, "CDVDPlayer::Process - Seeking to catch up");
m_SpeedState.lastseekpts = (int)DVD_TIME_TO_MSEC(m_clock.GetClock());
m_SpeedState.needsync = true;
int iTime = DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset + 500000.0 * m_playSpeed / DVD_PLAYSPEED_NORMAL);
m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true, false));
error = (int)DVD_TIME_TO_MSEC(m_clock.GetClock()) - m_SpeedState.lastseekpts;

if(abs(error) > 1000)
{
CLog::Log(LOGDEBUG, "CDVDPlayer::Process - Seeking to catch up");
m_SpeedState.lastseekpts = (int)DVD_TIME_TO_MSEC(m_clock.GetClock());
int iTime = DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset + 1000000.0 * m_playSpeed / m_playSpeed);
m_messenger.Put(new CDVDMsgPlayerSeek(iTime, (GetPlaySpeed() < 0), true, false, false, true, false));
}
}
}
}
Expand Down Expand Up @@ -2574,11 +2589,12 @@ void CDVDPlayer::HandleMessages()
m_OmxPlayerState.av_clock.OMXSetSpeed(speed);
CLog::Log(LOGDEBUG, "%s::%s CDVDMsg::PLAYER_SETSPEED speed : %d (%d)", "CDVDPlayer", __FUNCTION__, speed, m_playSpeed);
}
else if ((speed == DVD_PLAYSPEED_NORMAL) && m_SpeedState.needsync)
else if ((speed == DVD_PLAYSPEED_NORMAL) && m_playSpeed != DVD_PLAYSPEED_NORMAL)
{
int64_t iTime = (int64_t)DVD_TIME_TO_MSEC(m_clock.GetClock() + m_State.time_offset);
m_messenger.Put(new CDVDMsgPlayerSeek(iTime, true, true, false, false, true));
m_SpeedState.needsync = false;
if (m_State.disptime != DVD_NOPTS_VALUE)
iTime = m_State.disptime;
m_messenger.Put(new CDVDMsgPlayerSeek(iTime, m_playSpeed < 0, true, false, false, true));
}

// if playspeed is different then DVD_PLAYSPEED_NORMAL or DVD_PLAYSPEED_PAUSE
Expand Down
1 change: 0 additions & 1 deletion xbmc/cores/dvdplayer/DVDPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,6 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
int64_t lasttime;
int lastseekpts;
double lastabstime;
bool needsync;
} m_SpeedState;

int m_errorCount;
Expand Down
15 changes: 10 additions & 5 deletions xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,8 +1158,8 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
return result | EOS_DROPPED;
}

if (iSleepTime > 0.05)
iSleepTime = 0.05;
if (iSleepTime > DVD_MSEC_TO_TIME(20))
iSleepTime = DVD_MSEC_TO_TIME(20);
}
else if (m_speed > DVD_PLAYSPEED_NORMAL)
{
Expand All @@ -1177,8 +1177,8 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
return result | EOS_DROPPED;
}

if (iSleepTime > 0.05)
iSleepTime = 0.05;
if (iSleepTime > DVD_MSEC_TO_TIME(20))
iSleepTime = DVD_MSEC_TO_TIME(20);
}

// sync clock if we are master
Expand Down Expand Up @@ -1212,7 +1212,12 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
mDisplayField = FS_BOT;
}

int buffer = g_renderManager.WaitForBuffer(m_bStop, std::max(DVD_TIME_TO_MSEC(iSleepTime) + 500, 50));
// make sure waiting time is not negative
int maxWaitTime = std::max(DVD_TIME_TO_MSEC(iSleepTime) + 500, 50);
// don't wait when going ff
if (m_speed > DVD_PLAYSPEED_NORMAL)
maxWaitTime = 0;
int buffer = g_renderManager.WaitForBuffer(m_bStop, std::max(DVD_TIME_TO_MSEC(iSleepTime) + 500, 10));
if (buffer < 0)
{
m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate);
Expand Down

0 comments on commit 977976f

Please sign in to comment.