Index: libs/libmythtv/mythplayer.h =================================================================== --- libs/libmythtv/mythplayer.h (revision 26691) +++ libs/libmythtv/mythplayer.h (working copy) @@ -667,6 +667,11 @@ int ffrew_skip; + float ffw_fps; + float dis_fps; + int frame_skip; + int missed_frames; + // Audio and video synchronization stuff VideoSync *videosync; int avsync_delay; Index: libs/libmythtv/mythplayer.cpp =================================================================== --- libs/libmythtv/mythplayer.cpp (revision 26691) +++ libs/libmythtv/mythplayer.cpp (working copy) @@ -232,7 +232,8 @@ next_play_speed(1.0f), next_normal_speed(true), play_speed(1.0f), normal_speed(true), frame_interval((int)(1000000.0f / 30)), m_frame_interval(0), - ffrew_skip(1), + ffrew_skip(1), ffw_fps(0.0f), dis_fps(0.0f), frame_skip(0), + missed_frames(0), // Audio and video synchronization stuff videosync(NULL), avsync_delay(0), avsync_adjustment(0), avsync_avg(0), @@ -2793,13 +2794,22 @@ { if (ffrew_skip > 0) { - long long delta = decoder->GetFramesRead() - framesPlayed; - long long real_skip = CalcMaxFFTime(ffrew_skip + delta) - delta; + long long curFrame = decoder->GetFramesPlayed(); + long long real_skip = CalcMaxFFTime(frame_skip); + long long targetFrame = curFrame + real_skip - missed_frames; if (real_skip >= 0) { - long long frame = decoder->GetFramesRead() + real_skip; - decoder->DoFastForward(frame, false); + decoder->DoFastForward(targetFrame, false); } + long long seekFrame = decoder->GetFramesPlayed(); + if (seekFrame > targetFrame) + missed_frames = seekFrame - targetFrame; + else + missed_frames = 0; + VERBOSE(VB_PLAYBACK, LOC + QString("FFW : " + "curFrame %1 targetFrame %2 seekFrame %3 real_skip %4 missed_frames %5") + .arg(curFrame).arg(targetFrame).arg(seekFrame).arg(real_skip) + .arg(missed_frames)); } else if (CalcRWTime(-ffrew_skip) >= 0) { @@ -2810,10 +2820,21 @@ bool MythPlayer::DecoderGetFrameREW(void) { - long long curFrame = decoder->GetFramesRead(); - bool toBegin = -curFrame > ffrew_skip; - long long real_skip = (toBegin) ? -curFrame : ffrew_skip; - return decoder->DoRewind(curFrame + real_skip, false); + long long curFrame = decoder->GetFramesPlayed(); + bool toBegin = -curFrame > frame_skip; + long long real_skip = (toBegin) ? -curFrame : frame_skip; + long long targetFrame = curFrame + real_skip + missed_frames; + bool ret = decoder->DoRewind(targetFrame, false); + long long seekFrame = decoder->GetFramesPlayed(); + if (seekFrame < targetFrame) + missed_frames = targetFrame - seekFrame; + else + missed_frames = 0; + VERBOSE(VB_PLAYBACK, LOC + QString("REW : " + "curFrame %1 targetFrame %2 seekFrame %3 real_skip %4 missed_frames %5") + .arg(curFrame).arg(targetFrame).arg(seekFrame).arg(real_skip).arg(missed_frames)); + return ret; + } bool MythPlayer::DecoderGetFrame(DecodeType decodetype, bool unsafe) @@ -3090,12 +3111,22 @@ frame_interval = (int) (1000000.0f * ffrew_skip / video_frame_rate / temp_speed); videosync->setFrameInterval(frame_interval); + ffw_fps = play_speed * video_frame_rate; // how many fps for ffw/rew + dis_fps = 1000000.0f / (float)frame_interval; // display fps for ffw/rew + frame_skip = ffw_fps / dis_fps; // how many frames to skip for each frame_interval + VERBOSE(VB_PLAYBACK, LOC + "FFW/REW : " + + QString("ffw_fps: %1 dis_fps: %2 frame_skip: %3 ffrew_skip %4") + .arg(ffw_fps).arg(dis_fps).arg(frame_skip).arg(ffrew_skip)); + VERBOSE(VB_PLAYBACK, LOC + "Play speed: " + QString("rate: %1 speed: %2 skip: %3 => new interval %4") .arg(video_frame_rate).arg(play_speed) .arg(ffrew_skip).arg(frame_interval)); + if (videoOutput) + videoOutput->ClearAfterSeek(); // clear video buffers + if (videoOutput && videosync) { // We need to tell it this for automatic deinterlacer settings