使用 AVPlayer 时保持良好的滚动性能 [英] Maintaining good scroll performance when using AVPlayer

查看:19
本文介绍了使用 AVPlayer 时保持良好的滚动性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个有集合视图的应用程序,并且集合视图的单元格可以包含视频.现在我正在使用 AVPlayerAVPlayerLayer 显示视频.不幸的是,滚动性能很糟糕.看起来 AVPlayerAVPlayerItemAVPlayerLayer 在主线程上做了很多工作.他们不断地取出锁,等待信号量等等,这会阻塞主线程并导致严重的丢帧.

I'm working on an application where there is a collection view, and cells of the collection view can contain video. Right now I'm displaying the video using AVPlayer and AVPlayerLayer. Unfortunately, the scrolling performance is terrible. It seems like AVPlayer, AVPlayerItem, and AVPlayerLayer do a lot of their work on the main thread. They are constantly taking out locks, waiting on semaphores, etc. which is blocking the main thread and causing severe frame drops.

有什么办法可以让AVPlayer停止在主线程上做这么多事情?到目前为止,我尝试过的任何方法都无法解决问题.

Is there any way to tell AVPlayer to stop doing so many things on the main thread? So far nothing I've tried has solved the problem.

我还尝试使用 AVSampleBufferDisplayLayer 构建一个简单的视频播放器.使用它我可以确保一切都发生在主线程之外,并且我可以在滚动和播放视频时达到 ~60fps.不幸的是,这种方法的级别要低得多,并且它不提供诸如音频播放和开箱即用的时间清理之类的功能.有没有什么办法可以用 AVPlayer 获得类似的性能?我更愿意使用它.

I also tried building a simple video player using AVSampleBufferDisplayLayer. Using that I can make sure that everything happens off the main thread, and I can achieve ~60fps while scrolling and playing video. Unfortunately that method is much lower level, and it doesn't provide things like audio playback and time scrubbing out of the box. Is there any way to get similar performance with AVPlayer? I'd much rather use that.

在深入研究之后,使用 AVPlayer 似乎不可能实现良好的滚动性能.创建一个 AVPlayer 并与一个 AVPlayerItem 实例相关联会启动一堆工作,这些工作会跳到主线程上,然后等待信号量并尝试获取一堆锁.随着滚动视图中视频数量的增加,主线程暂停的时间会显着增加.

After looking into this more, it doesn't look like it's possible to achieve good scrolling performance when using AVPlayer. Creating an AVPlayer and associating in with an AVPlayerItem instance kicks off a bunch of work which trampolines onto the main thread where it then waits on semaphores and tries to acquire a bunch of locks. The amount of time this stalls the main thread increases quite dramatically as the number of videos in the scrollview increases.

AVPlayer dealloc 似乎也是一个大问题.Dealloc'ing AVPlayer 也试图同步一堆东西.同样,随着您创建更多玩家,情况会变得非常糟糕.

AVPlayer dealloc also seems to be a huge problem. Dealloc'ing an AVPlayer also tries to synchronize a bunch of stuff. Again, this gets extremely bad as you create more players.

这非常令人沮丧,它使 AVPlayer 几乎无法用于我正在尝试做的事情.像这样阻塞主线程是一件很业余的事情,所以很难相信 Apple 工程师会犯这种错误.不管怎样,希望他们能尽快解决这个问题.

This is pretty depressing, and it makes AVPlayer almost unusable for what I'm trying to do. Blocking the main thread like this is such an amateur thing to do so it's hard to believe Apple engineers would've made this kind of mistake. Anyways, hopefully they can fix this soon.

推荐答案

尽可能在后台队列中构建你的 AVPlayerItem(有些操作你必须在主线程上做,但你可以做设置操作并等待视频属性加载到后台队列 - 非常仔细地阅读文档).这涉及到 KVO 的伏都教舞蹈,真的不好玩.

Build your AVPlayerItem in a background queue as much as possible (some operations you have to do on the main thread, but you can do setup operations and waiting for video properties to load on background queues - read the docs very carefully). This involves voodoo dances with KVO and is really not fun.

AVPlayer 等待 AVPlayerItem 的状态变为 AVPlayerItemStatusReadyToPlay 时会发生打嗝.为了减少您想要做的打嗝的长度,在将 AVPlayerItem 分配给 AVPlayer 之前,在后台线程上使其更接近 AVPlayerItemStatusReadyToPlay.

The hiccups happen while the AVPlayer is waiting for the AVPlayerItems status to become AVPlayerItemStatusReadyToPlay. To reduce the length of the hiccups you want to do as much as you can to bring the AVPlayerItem closer to AVPlayerItemStatusReadyToPlay on a background thread before assigning it to the AVPlayer.

自从我真正实现这个已经有一段时间了,但是 IIRC 导致主线程阻塞是因为底层 AVURLAsset 的属性是延迟加载的,如果你不自己加载它们,当 AVPlayer 想要播放时,它们会在主线程上忙碌加载.

It's been a while since I actually implemented this, but IIRC the main thread blocks are caused because the underlying AVURLAsset's properties are lazy-loaded, and if you don't load them yourself, they get busy-loaded on the main thread when the AVPlayer wants to play.

查看 AVAsset 文档,尤其是关于 AVAsynchronousKeyValueLoading 的内容.我认为我们需要在 AVPlayer 上使用资产之前加载 durationtracks 的值以最小化主线程块.可能我们还必须遍历每个轨道并对每个段执行 AVAsynchronousKeyValueLoading,但我不记得 100%.

Check out the AVAsset documentation, especially the stuff around AVAsynchronousKeyValueLoading. I think we needed to load the values for duration and tracks before using the asset on an AVPlayer to minimize the main thread blocks. It's possible we also had to walk through each of the tracks and do AVAsynchronousKeyValueLoading on each of the segments, but I don't remember 100%.

这篇关于使用 AVPlayer 时保持良好的滚动性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆