简体   繁体   English

视频延迟和FPS在触摸屏上落在Android Lollipop上

[英]Video Lag and FPS drop on Android Lollipop on touching screen

I am using MediaCodec to play 1080p@60fps video. 我正在使用MediaCodec播放1080p @ 60fps的视频。 This is on freescale SabreSD platform with Android Lollipop 5.1. 这是在具有Android Lollipop 5.1的飞思卡尔SabreSD平台上。

Initially because of BufferQueue Synchronous Mode, the FPS was way below 60.I could now manage to play at 70FPS by changing the BufferQueue to Asynchronous as in JB. 最初由于BufferQueue同步模式,FPS低于60.我现在可以通过将BufferQueue更改为Asynchronous来像JB中一样以70FPS的速度播放。

Now the next challenge I am facing is the video lags and FPS drops drastically to 40 when I start interacting with the screen (pulling down notification bar , pressing volume button etc). 现在,我面临的下一个挑战是视频滞后,当我开始与屏幕互动时(下拉通知栏,按下音量按钮等),FPS急剧下降至40。

So I ran rafika MultiSurfaceActivity and Record GL, I can see all the test play smoothly when no screen is touched or disturbed, but as soon as I start scrolling the notification bar from top and continue that for long time, the fps gets reduced to 35-40FPS. 因此,我运行了rafika MultiSurfaceActivity和Record GL,当没有触摸或打扰屏幕时,我可以看到所有测试顺利进行,但是一旦我从顶部开始滚动通知栏并持续很长时间,fps就会降低到35 -40FPS。

I have confirmed the same test on Kitkat 4.4.2 and JB 4.2.2 and they seems to work fine. 我已经在Kitkat 4.4.2和JB 4.2.2上确认了相同的测试,它们似乎工作正常。

Same behaviour when playing MP4 from Gallery. 从图库播放MP4时,行为相同。 The video gets stuck and lags a lot when we start playing with Notification bar 当我们开始使用通知栏播放时,视频卡住并且滞后很多

Can anyone explain what has change from Kitkat to Lollipop which can cause this issue (VSync, Triple Buffering ?). 谁能解释从奇巧(Kitkat)到棒棒糖(Lollipop)的哪些变化会导致此问题(垂直同步,三重缓冲)?

Regurgitating a bit from the Grafika issue tracker : Grafika问题追踪器反省一下

The bouncing ball is software-rendered, so anything that soaks up CPU time is going to make it slow down. 弹跳球是由软件渲染的,因此占用CPU时间的任何事情都会使其变慢。 On devices with medium-grade CPUs and big displays (eg Nexus 10) it never gets close to 60fps. 在配备中级CPU和大显示屏的设备(例如Nexus 10)上,它永远不会接近60fps。 So a slowdown while you are playing with the nav bar doesn't surprise me, but if it continues to be slow even after you stop playing with the nav bar, then that's a little weird. 因此, 您使用导航栏播放时,放慢速度并不会让我感到惊讶,但是,即使您停止使用导航栏后,放慢速度仍然很慢,那还是有点奇怪。

Video playback should be less affected, as that does less with the CPU. 视频播放的影响应该较小,因为对CPU的影响较小。

Investigation into such problems usually begins by using systrace to capture traces in "good" and "bad" states, and comparing the two. 对此类问题的调查通常开始于使用systrace捕获处于“良好”和“不良”状态的跟踪,然后将两者进行比较。

The key point of BufferQueue "async mode" is to allow frames to drop if the consumer can't keep up with the producer. BufferQueue“异步模式”的关键是,如果使用者无法跟上生产者的速度,允许丢帧。 It's primarily meant for SurfaceTexture, where producer and consumer are in the same app, potentially on the same thread, so having the producer stall waiting for the consumer could cause the program to hang. 这主要是针对SurfaceTexture,其中生产者和使用者位于同一个应用程序中,并且可能在同一线程上,因此让生产者停滞等待使用者可以导致程序挂起。 I'm not sure what you mean by needing it to exceed 60fps, but I would guess you're throwing frames at the display faster than it can render them... so you're not really increasing the frame rate, you're just using the BufferQueue to drop the frames instead of using Choreographer to decide when you need to drop them yourself. 我不确定需要超过60fps的意思是什么,但是我猜想您在显示器上投帧的速度快于它可以渲染帧的速度……所以您并没有真正提高帧速率,只是使用BufferQueue放下帧,而不是使用Choreographer决定何时需要自己放下帧。

In any event, I left Google back in June 2014, well before Lollipop was completed. 无论如何,我在2014年6月(即棒棒糖完成之前)就离开了Google。 If something works correctly on KitKat but weirdly on Lollipop, I'm afraid I can't provide much insight. 如果某些东西在KitKat上正常运行,但在Lollipop上却奇怪,我恐怕无法提供太多见解。 If you can reproduce the behavior easily, it might be worth capturing a video that demonstrates the problem (point a second smart phone at the device exhibiting the problem, so they can see how you manipulate the device) and filing a bug on http://b.android.com/ . 如果您可以轻松地重现该行为,那么可能值得捕获一个演示问题的视频(将第二个智能手机指向出现问题的设备,以便他们可以看到您如何操作该设备)并在http:/上提交错误。 /b.android.com/


Some traces uploaded by the OP: OP上传的一些痕迹:

Looking at the kitkat trace, something weird is going on in SurfaceFlinger. 查看kitkat痕迹,SurfaceFlinger中发生了一些奇怪的事情。 The main thread is sitting in postFrameBuffer for a very long time (23-32ms). 主线程在postFrameBuffer放置了很长时间(23-32ms)。 It eventually wakes up, and the CPU row suggests it was waiting on activity from a "galcore daemon", which I'm not familiar with (seems particular to Vivante GPU). 最终它醒来了,CPU行提示它正在等待我不熟悉的“ galcore守护程序”(似乎是Vivante GPU特有的)的活动。

The lollipop traces only show the CPU rows, as if the capture were done without the necessary tags. 棒棒糖跟踪仅显示CPU行,就好像捕获是在没有必要标签的情况下进行的。 I don't believe the systrace capture command changed significantly between kitkat and lollipop, so I'm puzzled as to why the user-space-initiated logging would vanish but the kernel thread scheduling stuff would remain. 我不相信kittrace和lollipop之间的systrace capture命令不会发生显着变化,因此我为为什么用户空间启动的日志记录消失而内核线程调度的东西仍然存在感到困惑。 Make sure you have sched gfx view specified. 确保已指定了sched gfx view


The newer lollipop traces only have about a second of good data. 较新的棒棒糖痕迹只有大约一秒的良好数据。 When you see "Did Not Finish" it means a "start" record had no matching "end" record. 当您看到“未完成”时,表示“开始”记录没有匹配的“结束”记录。 You can increase the systrace logging buffer size with the -b flag. 您可以使用-b标志来增加systrace日志记录缓冲区的大小。 I think there's enough there though. 我认为那里足够了。

Looking at the /system/bin/surfaceflinger row you can see that, in the "good" trace, postFrameBuffer usually finishes in about 16ms, but it's still waiting on galcore. 查看/system/bin/surfaceflinger行,您可以看到,在“良好”跟踪中, postFrameBuffer通常在16ms左右完成,但仍在galcore上等待。 Zoom in on 388ms (use WASD keys). 放大388ms(使用WASD键)。 At 388.196ms, on the CPU 2 row, you can see galcore do something. 在388.196ms,在CPU 2行上,您可以看到galcore做了一些事情。 Right after it completes, the thin line at the top of the surfaceflinger row changes from light grey (sleeping) to green (running). 完成后,Singleflinger行顶部的细线从浅灰色(睡眠)变为绿色(运行)。 At 388.548ms, again on CPU 2, galcore runs again, and right after that on the surfaceflinger row you see queueBuffer start to execute. 在388.548ms,再次在CPU 2上,galcore再次运行,然后紧接着在surfaceflinger行上,您看到queueBuffer开始执行。

The "bad" trace looks identical. “不良”痕迹看起来相同。 For example, you can see two galcore executions at 101.146ms and 101.666ms, with what appear to be similar effects on the surfaceflinger row. 例如,您可以在101.146毫秒和101.666毫秒处看到两个galcore执行,它们对surfaceflinger行的效果似乎相似。 The key difference is the time spent in postFrameBuffer , which is around 16ms for "good" and around 30ms for "bad". 关键的区别是花费在postFrameBuffer的时间,“好”大约为16毫秒,“坏”大约为30毫秒。

So this doesn't appear to be a behavioral shift; 因此,这似乎不是行为上的转变。 rather, things are taking longer and deadlines are being missed. 相反,事情花了更长的时间,错过了最后期限。

As far as I can tell, SurfaceFlinger is being held up by galcore daemon. 据我所知,SurfaceFlinger被galcore守护程序阻止。 This is true in both "good" and "bad" cases. 在“好”和“坏”情况下都是如此。 To see what the timing should look like you can run systrace on a Nexus device, or compare to traces from other devices (eg the one in this case study or this SO question ). 看到时机应该是什么样子,你可以在Nexus设备上运行systrace,或比较从其他设备(例如,一个在跟踪这个案例研究这太问题 )。 If you zoom in you can see doComposition executing in a few milliseconds, and postFrameBuffer finishing in a few tenths of a millisecond. 如果放大,则可以看到doComposition在几毫秒内执行,并且postFrameBuffer在几十分之一毫秒内完成。

Summing up: you don't have good and bad, you have bad and worse. 总结:你没有好与坏,你有坏有坏。 :-) I don't know what galcore is, but you'll likely need to have a conversation with the GPU OEM. :-)我不知道galcore是什么,但是您可能需要与GPU OEM进行对话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM