Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
player/video: treat av sync of large speed changes specially
This is basically just mostly ad hoc from looking at numbers. A large speed change is defined as a greater than 50% difference between the previous time frame value and the newly calculated one right after a speed change (arbitrary). When this is satisfied, there are two distinct possibilities: the time frame is either negative or positive. The negative case is actually surprisingly easy to solve. Negative time frame values are unacceptable since mpv is guaranteed to seek forward since the audio hasn't caught up yet. So just simply add a tiny negative value to mpctx->delay (to avoid AV from running away forever) and wait until the buffer goes positive again before returning back to normal. This prevents the frames from skipping forwards to weird places for at least normalish cases. The positive case is the tricky one. It has a bad tendency to lead to non-monotonic frame order (i.e. it can skip ahead, then go backwards, then back forwards again, etc.). This is because the initial frame after the speed change lingers on the screen for far too long which essentially causes havoc on the calculations and subsequent passes through the renderloop overcorrect in both directions until it settles on the "correct" frame and then proceeds normally. "Fix" this by basically doing some hacks. Since the source of the problem is mpctx->time_frame being too big, let's just arbitrarily reduce the value for a arbitrary amount of frames. Essentially what this does is smoothen out the change for a short period of time before we trust that the values are sane enough to allow the normal rendering to proceed. Up to 8x speed, this seems to work OK for me and the frames increas monotonically. This is probably about where the limit with this method is although going any higher will guarentee a/v desync anyways (you don't actually use speeds this stupid do you). The final thing here to consider is the display sync code path. It has similar problems, and the cause in this case is the calculated a_pos having a dramatic offset from the video pts which causes skipping frames when changing speed (mostly when you decreaase the speed though). In this case, what we do is simply hold the a_pos to the video pts until the a_pos catches back up to a reasonable difference. After that, allow the normal syncing to happen again.
- Loading branch information