0

我正在使用 MediaCodec 播放 1080p@60fps 视频。这是在带有 Android Lollipop 5.1 的飞思卡尔 SabreSD 平台上。

最初是因为 BufferQueue 同步模式,FPS 远低于 60。我现在可以通过将 BufferQueue 更改为 JB 中的异步来设法以 70FPS 播放。

现在我面临的下一个挑战是当我开始与屏幕交互(下拉通知栏、按下音量按钮等)时,视频延迟和 FPS 急剧下降到 40。

所以我运行了 rafika MultiSurfaceActivity 和 Record GL,当没有触摸或干扰屏幕时,我可以看到所有测试顺利播放,但是一旦我开始从顶部滚动通知栏并继续很长时间,fps 就会降低到 35 -40FPS。

我已经在 Kitkat 4.4.2 和 JB 4.2.2 上确认了相同的测试,它们似乎工作正常。

从画廊播放 MP4 时的行为相同。当我们开始使用通知栏播放时,视频卡住并滞后很多

谁能解释从 Kitkat 到 Lollipop 的变化可能导致这个问题(VSync,三重缓冲?)。

4

1 回答 1

2

Grafika 问题跟踪器中反省一下:

弹跳球是软件渲染的,所以任何占用 CPU 时间的东西都会让它变慢。在具有中等 CPU 和大显示器的设备(例如 Nexus 10)上,它永远不会接近 60fps。所以你玩导航栏时减速并不让我感到惊讶,但如果即使你停止使用导航栏后它仍然很慢,那就有点奇怪了。

视频播放应该受到的影响较小,因为这对 CPU 的影响较小。

对此类问题的调查通常从使用systrace捕获处于“好”和“坏”状态的跟踪并比较两者开始。

BufferQueue“异步模式”的关键在于,如果消费者跟不上生产者,允许丢帧。它主要用于 SurfaceTexture,其中生产者和消费者在同一个应用程序中,可能在同一个线程上,因此让生产者停止等待消费者可能会导致程序挂起。我不确定你需要它超过 60fps 是什么意思,但我猜你在显示器上扔帧的速度比渲染它们的速度要快......所以你并没有真正提高帧速率,你是只需使用 BufferQueue 来丢弃帧,而不是使用 Choreographer 来决定何时需要自己丢弃它们。

无论如何,我在 2014 年 6 月离开谷歌,早在 Lollipop 完成之前。如果某些东西在 KitKat 上正常工作,但在 Lollipop 上却很奇怪,恐怕我无法提供太多见解。如果您可以轻松重现该行为,则可能值得捕获演示问题的视频(将第二部智能手机指向出现问题的设备,以便他们可以看到您如何操作设备)并在http:/上提交错误/b.android.com/


OP上传的一些痕迹:

查看 kitkat 跟踪,SurfaceFlinger 中发生了一些奇怪的事情。主线程postFrameBuffer等待很长时间(23-32ms)。它最终醒来,CPU 行表明它正在等待来自我不熟悉的“galcore 守护进程”的活动(似乎特别适用于 Vivante GPU)。

棒棒糖跟踪仅显示 CPU 行,就好像捕获是在没有必要标签的情况下完成的。我不相信 systrace capture 命令在 kitkat 和 lollipop 之间发生了显着变化,所以我很困惑为什么用户空间启动的日志记录会消失,但内核线程调度的东西会保留。确保您已sched gfx view指定。


较新的棒棒糖痕迹只有大约一秒钟的良好数据。当您看到“未完成”时,这意味着“开始”记录没有匹配的“结束”记录。-b您可以使用该标志增加 systrace 日志记录缓冲区大小。我认为那里已经足够了。

查看该/system/bin/surfaceflinger行,您可以看到,在“良好”跟踪中,postFrameBuffer通常在大约 16 毫秒内完成,但它仍在等待 galcore。放大 388 毫秒(使用 WASD 键)。在 388.196ms 时,在 CPU 2 行上,你可以看到 galcore 在做一些事情。完成后,surfaceflinger 行顶部的细线从浅灰色(睡眠)变为绿色(运行)。在 388.548 毫秒,再次在 CPU 2 上,galcore 再次运行,然后在 Surfaceflinger 行上您看到queueBuffer开始执行。

“坏”的痕迹看起来是一样的。例如,您可以在 101.146ms 和 101.666ms 看到两次 galcore 执行,在 surfaceflinger 行上似乎有类似的效果。关键区别在于花费的时间postFrameBuffer,“好”大约为 16 毫秒,“坏”大约为 30 毫秒。

所以这似乎不是行为转变。相反,事情需要更长的时间,并且会错过最后期限。

据我所知,SurfaceFlinger 被 galcore 守护进程阻止。在“好”和“坏”的情况下都是如此。要查看时间应该是什么样子,您可以在 Nexus 设备上运行 systrace,或与其他设备的跟踪进行比较(例如,本案例研究中的那个或这个 SO 问题)。如果放大,您可以看到doComposition在几毫秒内执行,并postFrameBuffer在十分之几毫秒内完成。

总结:没有好坏之分,有坏有坏。:-) 我不知道 galcore 是什么,但您可能需要与 GPU OEM 进行对话。

于 2016-04-17T18:34:59.127 回答