AVPlayer seek tolerance before and after are incorrectly handled

Originator:defagos
Number:rdar://44904505 Date Originated:October 1st 2018
Status:Closed Resolved:
Product:iOS SDK Product Version:All
Classification:Bug Reproducible:Always
 
Area:
AVFoundation

Summary:

`AVPlayer` and `AVPlayerItem` offer a `-seekToTime:toleranceBefore:toleranceAfter:completionHandler:` method. According to the documentation https://developer.apple.com/documentation/avfoundation/avplayer/1387741-seektotime:

"The time seeked to will be within the range [time-beforeTolerance, time+afterTolerance], and may differ from the specified time for efficiency. You can request sample accurate seeking by passing a time value of kCMTimeZero for both toleranceBefore and toleranceAfter"

Sample accurate seeking obtained by setting zero tolerances works as specified. The behavior observed when using non-zero tolerances is incorrect, though, and the time to which the player seeks might sometimes lie outside the defined range.

Steps to Reproduce:

A sample project has been attached. Using standard `AVPlayerViewController` and `AVPlayer`, playback is prepared and the player is asked to seek to some position, with various tolerance settings. The stream played is Apple HLS Bebop with chunk size of ~10 seconds. Three setups are provided:

1. Sample accurate seeking to position t = 219 seconds, i.e. all tolerances set to zero. The player exactly seeks to 219 seconds, which is correct.

2. Seeking to t = 219 seconds with a 1 second tolerance before. The player is allowed to efficiently seek within the range [218; 219] if possible. What is observed, though, is that the player efficiently seeks to t = 210 seconds, outside the allowed range.

3. Seeking to t = 215 seconds with a 1 second tolerance after. The player is allowed to efficiently seek within the range [215; 216] if possible. What is observed, though, is that the player efficiently seeks to t = 210 seconds, outside the allowed range.

Expected Results:

The player should always seek to a location in [time-beforeTolerance, time+afterTolerance]. If it cannot seek efficiently within this range, it should start at `time`, though less efficiently.

In the examples 2 and 3 above, the player should therefore start inefficiently at 219 and 215 seconds, respectively.

We also expect the following behavior for tolerance settings letting the player find an efficient position:

4. Seeking to t = 219 seconds with a 10 second tolerance before. The player is allowed to efficiently seek within the range [209; 219] if possible. Since a chunk boundary is found near 210 seconds, the player can seek there efficiently.

5. Seeking to t = 216 seconds with a 10 second tolerance after. The player is allowed to efficiently seek within the range [216; 226] if possible. Since a chunk boundary is found near 220 seconds, the player can seek there efficiently.

Actual Results:

If non-zero tolerance settings have been set, the player always finds an efficient seek position, but this position might (depending on chunk size and tolerance settings) incorrectly fall outside the required range.

Version/Build:

iOS 12 SDK.

Configuration:

iPhone 5C (9.3.2), iPad Air 2 (10.3.1), iPhone 7+ (11.0.3), iPhone X (12.0).

Comments

Fixed

Apparently as of iOS 14 (cannot tell in which version, hopefully in iOS 14.0).

Example

An example has been attached to this issue. The source code can be found here: https://github.com/defagos/radars/tree/master/seek-tolerance.


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!