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

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

问题描述

我正在开发一个有集合视图的应用程序,集合视图的单元格可以包含视频。现在我正在使用 AVPlayer AVPlayerLayer 显示视频。不幸的是,滚动性能很糟糕。好像 AVPlayer AVPlayerItem AVPlayerLayer 做一个很多他们在主线程上的工作。他们不断拿出锁,等待信号量等等,这阻碍了主线程并导致严重的帧丢失。

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 几乎无法用于我正在尝试做的事情。阻止像这样的主线程这样做是一件非常业余的事情,很难相信苹果工程师会犯这样的错误。无论如何,希望他们能尽快解决这个问题。

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 更接近 AVPlayerItemStatusReadyToPlay on在将其分配给 AVPlayer 之前的后台线程。

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 最小化主线程块。我们可能还需要遍历每个轨道并在每个段上执行 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天全站免登陆