vimeo / VIMVideoPlayer

Deprecated: Please use [PlayerKit]( https://github.com/vimeo/PlayerKit) instead.
MIT License
281 stars 62 forks source link

VIM-4496: No Playback if Already in Airplay Mode #64

Closed nicolelehrer closed 8 years ago

nicolelehrer commented 8 years ago

Ticket

Required for Vimeans only VIM-4496

Ticket Summary

To support DRM, we need to directly access the player asset and set its delegate. See changes to playVideoWithURL: captured here: https://github.vimeows.com/MobileApps/Vimeo-iOS/pull/938/files

As a result, we're now using setAsset: instead of setURL:. This left local playback unaffected. But in airplay mode, the player never received a status change that the player item was ready to play. (If a video was already playing, it could be air played, but the next video would not play).

It's not clear why this was happening, but the way in which we create the asset seems like it could be the culprit. The init method we used specified that we should pre-load "tracks". This in effect excluded "duration" as a key to be preloaded. The docs say:

"Unless you omit @"duration" from the array of asset keys you pass to 
+playerItemWithAsset:automaticallyLoadedAssetKeys: or -initWithAsset:automaticallyLoadedAssetKeys:, 
the value of this property will accord with the properties of the underlying AVAsset 
and the current state of playback once the receiver becomes ready to play."

It's interesting that the most basic player Item creation method playerItemWithAsset (which is what this PR suggests we use) does not exclude the duration key. The docs say that calling playerItemWithAsset is equivalent to +playerItemWithAsset:automaticallyLoadedAssetKeys: and passing @[ @"duration" ] as the value of automaticallyLoadedAssetKeys.

Also, it's not clear if we necessarily need to pre-load tracks because it seems we don't need to access them outside of the context of playback. The docs say

If you need to access information about the asset before you enqueue it for playback, 
you can use the methods of the AVAsynchronousKeyValueLoading protocol to load 
the values you need. Alternatively, AVPlayerItem can automatically load the 
needed asset data for you by passing the desired set of keys 
to its init(asset:automaticallyLoadedAssetKeys:) initializer. When the player item is ready 
to play, those asset properties will have been loaded and are ready for use.

From an older WWDC talk - 2014

If you anticipate the use of a particular property later in your application, 
you can still request all of them together using loadValuesAsynchronouslyForKeys and 
completionHandler. You can parse in an array of keys which AVFoundation will load together and 
your completionHandler is called once you are done loading these properties. 
You no longer have to load tracks before playback begins. 
This has changed since the last time we talked about best practices. 
In fact, this has changed since iOS 5. You really only need to load those properties you 
would directly use in your application.

Since I couldn't find a clear link between our playback flow, airplay, and the creation of assets, the snippets above were meant to show it's likely not necessary to preload tracks, it could be disrupting something in our current playback flow and we can adopt the simpler method.

Implementation Summary

Updated the init method used for creating our AVAsset.

How to Test

huebnerob commented 8 years ago

build this please

edit: thought I was in the app repo :P

huebnerob commented 8 years ago

Looks great @nicole 👍

nicolelehrer commented 8 years ago

Thanks a lot @huebnerob. @jasonhawkins - this was the PR I was hoping you could do a cursory look at given Rob's reviewed it. Just another head check on the reasoning in the PR description since I believe I'm modifying some fairly old player stuff.