AVAudioPlayer enters an infinite loop if pause() is called very close to the end, and then playback is resumed with play()
| Originator: | digipom | ||
| Number: | rdar://32664362 | Date Originated: | June 8th, 2017 |
| Status: | New | Resolved: | |
| Product: | iOS SDK | Product Version: | 10.3.2 |
| Classification: | Serious bug | Reproducible: | Yes |
Area:
AVFoundation
Summary:
When stopping an AVAudioPlayer close to the end and then playing it again, it will enter into an infinite loop but without any audio being heard. The audio will not come back even after repeated play()/pause() attempts unless the player is de-inited and recreated.
Steps to Reproduce:
This can be reproduced by playing back audio, and then tapping pause just before the end. If done at the right moment, the playback will enter into an infinite loop without anything being heard.
This code will reproduce it:
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioPlayerDelegate {
var player: AVAudioPlayer?
var intercept: Bool = true
@IBOutlet weak var progressView: UIProgressView!
@IBOutlet weak var playButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let displayLink = CADisplayLink.init(target: self, selector: #selector(pollCurrentTime))
displayLink.add(to: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func onPlayButtonTapped(_ sender: UIButton) {
let asset = NSDataAsset(name:"TestRecording")!
player = try! AVAudioPlayer(data: asset.data, fileTypeHint: "m4a")
player!.delegate = self
player!.play()
playButton.isEnabled = false
}
func pollCurrentTime() {
if let player = player {
progressView.progress = Float(player.currentTime / player.duration)
if intercept && progressView.progress > 0.97 {
intercept = false
player.pause()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
player.play()
}
}
} else {
progressView.progress = 0
}
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
cleanup()
}
func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) {
cleanup()
}
private func cleanup() {
self.player = nil
playButton.isEnabled = true
intercept = true
}
}
Expected Results:
This should not happen.
Observed Results:
Happens on iPhone 6, iOS 10.3.2
Version:
10.3.2 (14F89)
Notes:
Additional notes: Seems that currentTime goes to 0 even though we paused close to the end, but neither of the two delegate methods were called.
Configuration:
iPhone 6s
Comments
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!