iOS 14 AVKit regression: AVPlayer is not correctly released when a picture in picture controller is used

Originator:defagos
Number:rdar://FB8561088 Date Originated:Aug 28, 2020
Status:Open Resolved:
Product:iOS Product Version:14
Classification:Bug Reproducible:Always
 
Description of the problem:

I noticed an issue when running our apps (supporting picture in picture since iOS 9) on an iPhone running iOS 14 beta. If playing video content and closing our custom video player, sound still continues to play in the background. The only option for a user to stop the sound from playing is then to kill the application, which is bad from a user experience point of view. This problem did not exist in iOS 9 to 13.

I could trace back this issue to picture in picture, probably because of the internal OS changes currently made to support PiP on iPhones. When a picture in picture controller is used, the underlying AVPlayer instance is namely not correctly released anymore, and as a result sound still plays in the background, even after having removed all strong references to AVPlayer or AVPictureInPictureController. 

I could reproduce this issue on all iOS 14 beta versions (1 up to 6). I sadly have no iPad device running iOS 14 beta, but running the app in the simulator yields the same result. As of beta 6, the iPhone simulator is still not compatible with PiP yet, so I could not perform the same check for a simulated iPhone.

How to reproduce the problem:

I created a small iPhone / iPad sample project reproducing this issue. The app is very basic and instantiates an AVPlayer with an HLS video stream URL and displays its content within a view backed up with AVPlayerLayer. Once the player layer is ready, the picture in picture controller is prepared and can then be used to enter or exit PiP. The application itself is properly setup to allow the PiP feature to work (background modes & audio session).

Here is how you can reproduce the issue described above with this sample app:

1. Build and run the app on a real device running iOS 14, either an iPhone or iPad.
2. Tap on the "Play" button. The video starts playing.
3. Tap on the "Reset" button. The sound keeps playing in the background, with no way to stop it (except killing the app).

If you perform the same test on a device running iOS 13 (iPad with PiP or iPhone with no such capability), sound correctly stops after you press on "Reset". A check with Instruments clearly shows a dangling AVPlayer instance still existing on iOS 14, but not on iOS 13.

I added a few additional buttons and switches for you to play around and notice that this is actually related to PiP. Between attempts you should kill & restart the app on iOS 14 to avoid dangling AVPlayer references (this is not needed on iOS 13 since everything works fine for this version). Here is what is available:

1. A picture in picture toggle button, with which you can verify that the picture in picture controller is correctly attached to the layer and actually works. For simplicity I did not implement restoration or a full PiP user experience, of course.
2. A switch to enable or disable PiP entirely. If you toggle it off before starting playback, no PiP controller will be created internally. On iOS 14, you can see that after you pressed "Reset" the sound correctly stops, clearly indicating that the PiP controller is responsible of keeping a strong reference it should not.

Expected result:

When a player layer is attached to a picture in picture controller, the shared AVPlayer instance is correctly released after all other references to the player and to the PiP controller have been released.

Actual result:

When a player layer has been attached to a picture in picture controller, there will always remain a dangling AVPlayer strong reference somewhere, outside of the control of the application. As a result, content will continue to play in the background, forcing users to kill the app to get rid of it.

Comments

I can confirm that it is still an issue in iOS 15.1

Sample code

Available on GitHub: https://github.com/defagos/radars/tree/master/pip-leak

Initially reported for iOS 14 beta, but still an issue with iOS 14 final and 14.2 beta 1


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!