Understanding AVFoundation and MediaPlayer frameworks in iOS
Issue #210
Depending on what features we want to achieve, we need to go with either AVFoundation or MediaPlayer framework. As someone who worked with many apps that involve media playback, here are some of my observations
MPMoviePlayerController vs AVPlayer
At first, I use MPMoviePlayerController because it is very simple, in fact, it is a wrapper around AVPlayer. It offers a lot of useful notifications and properties.
But when my requirements change, a lot more features are needed, I need to change to AVPlayer to have more control. And that is the wisest decision I’ve ever made
You should use AVPlayer as soon as possible. Using it cost you just a little longer time than MPMoviePlayerController, but you have a lot of control.
Custom controls
When building your own player, the built in controls of MPMoviePlayerController may not satisfy your need. I see many questions on SO are about custom controls.
MPMoviePlayerController
You have to set controlStyle to MPMovieControlStyleNone, set up Timer because currentPlaybackTime is not KVO compliance
AVPlayer
AVPlayer has no built in controls, but it has addPeriodicTimeObserverForInterval:queue:usingBlock: that makes handling the current time easily. The nicer thing about periodTimeObserver is that “The block is also invoked whenever time jumps and whenever playback starts or stops”
Notification
MPMoviePlayerController
It has a lot of useful notifications, like MPMoviePlayerNowPlayingMovieDidChangeNotification, MPMoviePlayerLoadStateDidChangeNotification, MPMovieDurationAvailableNotification, …
AVPlayer
The AVPlayerItem has some notifications AVPlayerItemDidPlayToEndTimeNotification, AVPlayerItemPlaybackStalledNotification, …
If you want to have those same notifications as MPMoviePlayerController, you have to KVO some properties of AVPlayer like currentItem, currentTime, duration, … You have to read documents to make sure which property is KVO compliance
Seek
MPMoviePlayerController
You can change the currentPlaybackTime to seek, but it results in jumping, because of efficiency and buffer status. I have to manually disable slider during seeking
AVPlayer
AVPlayer has this seekToTime:toleranceBefore:toleranceAfter:completionHandler: which allows you to specify the tolerance. Very nice
Subtitle
MPMoviePlayerController
I have to schedule a timer that “wake” and “sleep” at the beginning and end time of a certain subtitle marker, respectively.
AVPlayer
AVPlayer has this addBoundaryTimeObserverForTimes:queue:usingBlock: that perfectly suits my need. I setup 2 boundary time observers, 1 for the beginning times, 1 for the end times. The beginning times is an array containing all beginning timestamps that a subtitle marker appears.
Time scale
AVPlayer uses CMTime that offers timescale, which is a more comfortable way to specify more accurate time
Volume
AVPlayer has volume property (relative to system volume) that allows me to programmatically changes the player volume
Playable duration
MPMoviePlayerController
It has playableDuration property
AVPlayer
You have to compute yourself. See http://stackoverflow.com/questions/6815316/how-can-i-get-the-playable-duration-of-avplayer
Full screen
MPMoviePlayerController achieves full screen mode by creating another UIWindow, you learn from this to support full screen using AVPlayer, too
Movie Source Type
MPMoviePlayerController
It has movieSourceType that provides clues to the playback system, hence improving load time
“ If you know the source type of the movie, setting the value of this property before playback begins can improve the load times for the movie content.”
AVPlayer
Read Handling Different Types of Asset on AV Foundation Programming Guide
“To create and prepare an HTTP live stream for playback. Initialize an instance of AVPlayerItem using the URL. (You cannot directly create an AVAsset instance to represent the media in an HTTP Live Stream.)”
AVAsset
AVPlayer allows you to access AVAsset, which provides you more information about the playback and load state
Allow a range within a video to be playable
AVPlayerItem has forwardPlaybackEndTime and reversePlaybackEndTime that is used to specify a range that the player can play. When forwardPlaybackEndTime is specified and the playhead passes this points, AVPlayerItem will trigger AVPlayerItemDidPlayToEndTimeNotification
But it doesn’t work in my case forwardPlaybackEndTime does not work
You can have many instances of AVPlayer playing at the same time
Read more
- AV Foundation Programming Guide
- WWDC 2011 Session 405 Exploring AV Foundation
- WWDC 2011 Session 415 Working With Media In AV Foundation
- WWDC 2014 Session 503 Mastering Modern Media Playback
- WWDC 2011 Session 406 AirPlay and External Displays in iOS apps
- AVPlayerDemo
- VKVideoPlayer
- ALMoviePlayerController
- AV Foundation Playing Videos
- AVPlayer and MPMoviePlayerController differences
- MPMoviePlayer Tips