Closed defagos closed 11 months ago
I finally could understand why sometimes we observed Picture in Picture being paused during restoration, not from the PiP overlay itself, but by starting playback of another content. This investigation and the related fix were made as part of #702.
Pauses occur when transitioning via PiP from some content A, played with a player supporting PiP, to some content B, played in the same player but not supporting PiP.
Compare:
Content A played with a player supporting PiP, transitioning via PiP to content B in the same player supporting PiP:
https://github.com/SRGSSR/pillarbox-apple/assets/170201/eea74446-2275-45ff-8ac2-69c5361d674f
Content A played with a player supporting PiP, transitioning via PiP to content B in the same player not supporting PiP:
https://github.com/SRGSSR/pillarbox-apple/assets/170201/64de7277-f7c6-4b8c-8070-0febd4693d93
In the first case playback continues, while in the second one playback is paused.
You might think that this case is convoluted but actually it isn't. The fact that a view supports PiP not only supposes that the video view has been configured appropriately, but also that the view itself is installed in the hierarchy and therefore could register itself with a Picture in Picture controller.
Depending on how a player user interface is implemented the view might not be immediately available, e.g. if the implementation only displays the video view once the media type is known (see #696 for a related issue that needed to be fixed as well). This is perfectly legitimate and can happen in practice. We have no way of preventing such implementations and we cannot have behaviors break just because of subtle layout implementation refactorings that are part of any development process.
Our implementation explicitly stops Picture in Picture using the dedicated API when a video view appears for the first time (via onAppear(perform:)
). To better understand what happens let us have a look at what we have if we remove the stop and let PiP playback continue in the overlay. We then simulate the stop by tapping the restoration button in the PiP overlay:
Content A played with a player supporting PiP, transitioning via PiP to content B in the same player supporting PiP:
https://github.com/SRGSSR/pillarbox-apple/assets/170201/8c203cfe-2afc-4f84-8cb5-e75ae8bef5f6
Content A played with a player supporting PiP, transitioning via PiP to content B in the same player not supporting PiP:
https://github.com/SRGSSR/pillarbox-apple/assets/170201/8bff9237-8984-4306-8a22-402452357ab6
We can easily understand what happens now:
AVPlayer
is the same (thus the content appearing twice). When stopping PiP the player is paused, which makes the other layer as well.To fix the issue visible in the second scenario we need to detach the player from the PiP layer before PiP is stopped, but only when the view we are transitioning to does not support PiP anymore. This way we avoid the player being shared and pausing playback in the other layer when PiP is closed:
https://github.com/SRGSSR/pillarbox-apple/assets/170201/217ca526-5965-4312-846e-09562e91b408
The programmatic PiP stop is not even needed in this case since this change forces PiP to close automatically. The stop is still needed for the first scenario, though, so that the PiP overlay is properly returned when transitioning to the same view supporting PiP.
Here are a few use cases as a reminder of expected behaviors that should possible to implement and test in the demo. This is of course no perfect replacement for proper unit testing but at least better than having nothing.
In all cases:
Note that the behaviors listed above are mostly a matter of proper route management. Our API, though, must have the flexibility so that these behaviors can be implemented.
https://github.com/SRGSSR/pillarbox-apple/assets/170201/2252466f-9fe4-4151-b73a-1a29ce97836b
PiP must be possible simultaneously with other views backed by separate models. Restoration must also be possible.
https://github.com/SRGSSR/pillarbox-apple/assets/170201/1d4dfe27-159c-49ed-a000-9223290c2384
https://github.com/SRGSSR/pillarbox-apple/assets/170201/a2b96848-a06d-4712-ad21-26f3b9e5ea93
https://github.com/SRGSSR/pillarbox-apple/assets/170201/4fd77658-67b0-4ea2-976c-bc2621ba4b40
If going through several contents played with the same model / player, the latest content must be restored (in the video below Couleur 3 is restored, not the first opened SWI content):
https://github.com/SRGSSR/pillarbox-apple/assets/170201/d37ab7e5-71a6-4c71-9756-2887e4eb3abb
Monoscopic display does not support PiP.
https://github.com/SRGSSR/pillarbox-apple/assets/170201/394341cc-f5ff-468f-aa6b-69c68408004b
https://github.com/SRGSSR/pillarbox-apple/assets/170201/758f59b3-0f50-4019-9b3a-a5cbe49e3bdf
VideoView
In this case PiP must be stopped since there can be at most a single VideoView
enabled for PiP, no matter to which model it is connected.
https://github.com/SRGSSR/pillarbox-apple/assets/170201/6e84c9c0-779d-42ac-8550-1ed21a89902f
https://github.com/SRGSSR/pillarbox-apple/assets/170201/f04082bd-d951-4238-ba14-91cbaf05f4b8
https://github.com/SRGSSR/pillarbox-apple/assets/170201/25469730-1817-4daf-b758-8a3a10c8ab90
https://github.com/SRGSSR/pillarbox-apple/assets/170201/f563f360-4cde-423e-8360-89a75649ae83
https://github.com/SRGSSR/pillarbox-apple/assets/170201/7d51f55c-1757-4a6c-9f72-e61c074ea97d
https://github.com/SRGSSR/pillarbox-apple/assets/170201/8d9c0700-38d4-445f-9b12-b45bc6090c86
https://github.com/SRGSSR/pillarbox-apple/assets/170201/f0817170-913e-4445-b011-d242378792f4
As a developer integrating Pillarbox I want to be able to implement PiP deeper in my application, so that users can browse the application while continuing playback using PiP.
As a Pillarbox user I want to be able to use the app while watching content.
Acceptance criteria
Hints
Tasks