IOS AVFOUNDATION播放基准

通过安德烈·波波夫 ( Andrey Popov)

随着iOS 11的引入,AVFoundation框架进行了一些更改,并扩展了新功能 。 因此,为了更好地理解和利用框架功能,以下是对去年在Apple WWDC上首次引入的AVFoundation Playback基准测试进展的介绍和评论。

AVFoundation功能

AVFoundation提供了用于多种多媒体操作的API,包括回放,图像捕获,导出和大量的编辑选项。

播放类型:
从本地存储: file:///.../example.MOV.
从将文件上传到的Web服务器,然后进行逐步下载: https://example.com/example.MOV.https://example.com/example.MOV.
一种更动态的方法是HTTP Live Streaming(HLS)。 HLS播放播放列表。 播放列表是.txt文件。 它包含#EXTINF标签。 标签包含段(segment1.ts等),每个段的长度为10秒(#EXTINF 10.001)。

视频6Mbit播放列表;
影片4Mbit播放清单;
视频2Mbit播放列表音频立体声播放列表;
音频环绕播放列表;

playlist.txt文件:
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-MAP:URI="patpmt.ts"
#EXTINF 10.001
segment1.ts
#EXTINF 10.001
segment2.ts

通常,默认URL与基本播放列表相关,该基本播放列表包含相同内容的多个播放列表,但根据传输速度,格式(有时甚至是语言)进行配置。

通过网络播放

今天, AVPlayerItem具有三个属性: playbackLikelyToKeepUpplaybackBufferFullplaybackBufferEmpty

在iOS 9及之前的版本中,AVFoundation客户端应控制渐进式下载属性,并等到它们设置AVPlayer.rate = 1之前,直到playbackLikelyToKeepUpplaybackBufferEmpty属性为true。

对于HTTP Live Streaming,您可以在用户开始播放后立即将AVPlayer.rate设置为1,并自动等待数据足够缓冲以开始播放。

在iOS 10,macOS Sierra和tvOS 10中,将应用与渐进式下载和HTTP实时流传输相同的规则。 您可以在敲击播放事件上设置AVPlayer.rate = 1或请求播放方法–同样。 在这种情况下,AVFoundation会自动等待以避免缓冲。

如果在播放期间网络连接丢失,则保留AVPlayer.rate = 1值。 缓冲会继续进行,只要加载了足够的数据,便会继续播放。

如果您将AVKit和MediaPlayer用于UI,则它们已经支持自动缓冲等待。 使用AVFoundation的应用程序直接使用新的API(automaticallyWaitsToMinimizeStalling)。 如果AVPlayer.automaticallyWaitsToMinimizeStalling值为false,则立即开始播放。

通过网络播放具有三种状态:暂停,等待和播放。 初始状态被暂停。

AVPlayer.rate是请求的应用程序回放速度。
AVPlayerItem.timebase.rate是播放速度。

iOS 10 AVFoundation主食

自动, AVPlayer.automaticallyWaitsToMinimizeStalling参数值为true。 AVPlayer.timeControlStatus - (Paused, WaitingToPlayAtSpecifiedRate, Playing)是播放器的状态。 在等待模式(WaitingToPlayAtSpecifiedRate)AVPlayer.reasonForWaitingToPlay参数报告此等待的原因。

AVQueuePlayer是回放队列,用于优化不同元素(AVPlaerItem)之间的过渡。 如果发生循环,则可以在一个AVAsset中创建多个AVPlayer元素。 AVQueuePlayer提供有关要播放的元素以及这些过渡的AVFoundation优化的信息。

跑步机效应

创建AVPlayerItem元素并将其添加到AVQueuePlayer队列中,同时设置.end属性。 当播放到达元素的末尾时,随着列表移至下一项,它将从队列中删除。 收到发生这种情况的通知后,您可以获取此元素,将其当前时间设置为开始,然后将其放置在队列的末尾。 使用stopObservingstartObserving方法来避免递归。

  覆盖函数funcValueValue(forKeyPath keyPath:String ?,对象:AnyObject ?,更改: 
  [NSKeyValueChangeKey:AnyObject] ?,上下文:UnsafeMutablePointer ?){ 
     如果context ==&ObserverContexts.currentItem { 
        后卫让玩家=玩家其他{返回} 
        如果player.items()。isEmpty { 
           //由于播放器项目不正确,播放队​​列被清空。  结束循环。 
  } 
  其他{ 
           如果让itemRemoved =更改?[。oldKey]为?  AVPlayerItem { 
              itemRemoved.seek(至:kCMTimeZero) 
              stopObserving()  
              player.insert(itemRemoved,after:nil) 
              startObserving() 
  }} 
  } 
  //其他...} 

AVPlayerLooper

AVplayerLoop实现了跑步机效果,创建了多个AVPleyerItem副本, AVPleyerItem副本在播放队列中循环移动。

  播放器= AVQueuePlayer()  
  playerLayer = AVPlayerLayer(玩家:玩家) 
  playerItem = AVPlayerItem(URL:videoURL) 
  playerLooper = AVPlayerLooper(玩家:玩家,templateItem:playerItem) 
  player.play()