Index: libs/libmythtv/decoderbase.h =================================================================== --- libs/libmythtv/decoderbase.h (revision 26683) +++ libs/libmythtv/decoderbase.h (working copy) @@ -136,6 +136,7 @@ virtual void UpdateFramesPlayed(void); long long GetFramesRead(void) const { return framesRead; }; + long long GetFramesPlayed(void) const { return framesPlayed; }; virtual QString GetCodecDecoderName(void) const = 0; virtual QString GetRawEncodingType(void) { return QString(); } Index: libs/libmythtv/mythplayer.h =================================================================== --- libs/libmythtv/mythplayer.h (revision 26683) +++ 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 26683) +++ 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), @@ -1637,6 +1638,8 @@ { float diverge = 0.0f; int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval; + VERBOSE(VB_PLAYBACK, QString("AVSync frameDelay %1 m_double_framerate %2") + .arg(frameDelay).arg(m_double_framerate)); // attempt to reduce fps for standalone PIP if (player_ctx->IsPIP() && framesPlayed % 2) { @@ -2787,13 +2790,21 @@ { if (ffrew_skip > 0) { - long long delta = GetDecoder()->GetFramesRead() - framesPlayed; - long long real_skip = CalcMaxFFTime(ffrew_skip + delta) - delta; + long long curFrame = GetDecoder()->GetFramesPlayed(); + long long real_skip = CalcMaxFFTime(frame_skip); + long long targetFrame = curFrame + real_skip - missed_frames; if (real_skip >= 0) { - long long frame = GetDecoder()->GetFramesRead() + real_skip; - GetDecoder()->DoFastForward(frame, false); + GetDecoder()->DoFastForward(targetFrame, false); } + long long newFrame = GetDecoder()->GetFramesPlayed(); + if (newFrame > targetFrame) + missed_frames = newFrame - targetFrame; + else + missed_frames = 0; + VERBOSE(VB_PLAYBACK, LOC + QString("FFWD : " + "curFrame %1 targetFrame %2 newFrame %3 real_skip %4 missed_frames %5") + .arg(curFrame).arg(targetFrame).arg(newFrame).arg(real_skip).arg(missed_frames)); } else if (CalcRWTime(-ffrew_skip) >= 0) { @@ -2804,10 +2815,20 @@ bool MythPlayer::DecoderGetFrameREW(void) { - long long curFrame = GetDecoder()->GetFramesRead(); - bool toBegin = -curFrame > ffrew_skip; - long long real_skip = (toBegin) ? -curFrame : ffrew_skip; - return GetDecoder()->DoRewind(curFrame + real_skip, false); + long long curFrame = GetDecoder()->GetFramesPlayed(); + bool toBegin = -curFrame > frame_skip; + long long real_skip = (toBegin) ? -curFrame : frame_skip; + long long targetFrame = curFrame + real_skip + missed_frames; + bool ret = GetDecoder()->DoRewind(targetFrame, false); + long long newFrame = GetDecoder()->GetFramesPlayed(); + if (newFrame < targetFrame) + missed_frames = targetFrame - newFrame; + else + missed_frames = 0; + VERBOSE(VB_PLAYBACK, LOC + QString("REW : " + "curFrame %1 targetFrame %2 newFrame %3 real_skip %4 missed_frames %5") + .arg(curFrame).arg(targetFrame).arg(newFrame).arg(real_skip).arg(missed_frames)); + return ret; } bool MythPlayer::DecoderGetFrame(DecodeType decodetype, bool unsafe) @@ -3057,6 +3078,7 @@ float last_speed = play_speed; play_speed = next_play_speed; normal_speed = next_normal_speed; + missed_frames = 0; bool skip_changed; if (play_speed > 0.0f && play_speed <= 3.0f) @@ -3067,7 +3089,8 @@ else { skip_changed = true; - int new_skip = ((uint)ceil(4.0 * fabs(play_speed) / 30)) * 30; + //int new_skip = ((uint)ceil(4.0 * fabs(play_speed) / 30)) * 30; + int new_skip = (int)(3.9f * fabs(play_speed)); if (play_speed < 0.0) new_skip = -new_skip; ffrew_skip = new_skip; @@ -3083,7 +3106,14 @@ float temp_speed = (play_speed == 0.0) ? audio.GetStretchFactor() : play_speed; frame_interval = (int) (1000000.0f * ffrew_skip / video_frame_rate / temp_speed); + ffw_fps = play_speed * video_frame_rate; + dis_fps = 1000000.0f / (float)frame_interval; + frame_skip = ffw_fps / dis_fps; + VERBOSE(VB_PLAYBACK, LOC + "FFW : " + + QString("ffw_fps: %1 dis_fps: %2 frame_skip: %3") + .arg(ffw_fps).arg(dis_fps).arg(frame_skip)); + VERBOSE(VB_PLAYBACK, LOC + "Play speed: " + QString("rate: %1 speed: %2 skip: %3 => new interval %4") .arg(video_frame_rate).arg(play_speed)