我想问一下,如果可以改善带有叠加视图的录制屏幕的FPS。
app的伪结构:
1)AppCompatActivity中的全屏FrameLayout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
...
>
<RelativeLayout
android:id="@+id/controls"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
...
>
<ImageView
...
/>
<TextView
...
/>
</RelativeLayout>
</RelativeLayout>
</FrameLayout>
2)使用SurfaceView进行相机预览:
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
3)获取SurfaceView(CameraPreview),将CameraPreview添加到FrameLayout,带到前面
mPreview = new CameraPreview(this, mCamera); //surfaceView
frameLayout.addView(mPreview); //add surfaceView to root: FrameLayout
controls.bringToFront(); //bring controls to top Z-order
4)创建输入曲面+创建虚拟显示并通过MediaProjection.createVirtualDisplay(...)
将虚拟显示渲染到曲面下一步使用MediaMuxer
进行音频/视频多路复用流。
第3点:问题
当我评论时,controls.bringToFront();
视频的视频大约为30FPS,但视频中没有叠加视图
当我取消注释行时:controls.bringToFront();
视频在视频中有叠加视图,但FPS只有~20。
OR
当我禁用CameraPreview
视频时有~30FPS,但没有相机预览。
问题可能出在叠加视图上。当我在设备上启用调试模式的透支时:see
相机预览超量1x(紫色)
ImageView透支2倍(绿色)
TextView过度抽取3x(粉红色)
当我在设备上启用调试模式下的GPU渲染时:see
我把所有的条都放在绿线下(16ms)。
也许我有一些效率低下的东西。目标是具有相同FPS的记录屏幕,具有/不具有覆盖视图。有可能吗?
使用screenrecord
命令和硬件编辑器进行测试:
A)启用了视图叠加;启用相机预览:
$ ./adb shell screenrecord --time-limit 10 --bit-rate 6000000 /storage/sdcard1/demo3.mp4
,结果是视频文件:1280 x 720; H.264 / AVC; 20FPS ;比特率:4585 kb / s。
硬件编辑器:
type | handle | hint | flag | tr | blnd | format | source crop (l,t,r,b) | frame | name
HWC | 557cf928d0 | 0000 | 0000 | 04 | 0100 | ? 00000011 | 0.0, 0.0, 1280.0, 720.0 | 0, 0, 720, 1280 | SurfaceView
HWC | 557cf40dd0 | 0000 | 0000 | 00 | 0105 | RGBA_8888 | 0.0, 0.0, 720.0, 1280.0 | 0, 0, 720, 1280 | com.example.test/com.example.test.RecordActivity
FB TARGET | 557cf3fd00 | 0000 | 0000 | 00 | 0105 | RGBA_8888 | 0.0, 0.0, 720.0, 1280.0 | 0, 0, 720, 1280 | HWC_FRAMEBUFFER_TARGET
B)禁用叠加(//controls.bringToFront();
),因此只启用了相机预览:
$ ./adb shell screenrecord --time-limit 10 --bit-rate 6000000 /storage/sdcard1/demo4.mp4
,结果是视频文件:1280 x 720; H.264 / AVC; 30FPS ;比特率:6684 kb / s。
硬件编辑器:
type | handle | hint | flag | tr | blnd | format | source crop (l,t,r,b) | frame | name
HWC | 557cf46610 | 0000 | 0000 | 04 | 0100 | ? 00000011 | 0.0, 0.0, 1280.0, 720.0 | 0, 0, 720, 1280 | SurfaceView
FB TARGET | 557cf3fd00 | 0000 | 0000 | 00 | 0105 | RGBA_8888 | 0.0, 0.0, 720.0, 1280.0 | 0, 0, 720, 1280 | HWC_FRAMEBUFFER_TARGET
C)仅启用android:id="@+id/frameLayout"
+ android:id="@+id/controls"
布局;启用相机预览:
$ ./adb shell screenrecord --time-limit 10 --bit-rate 6000000 /storage/sdcard1/demo5.mp4
,结果是视频文件:1280 x 720; H.264 / AVC; 30FPS ;比特率:4280 kbps。
硬件编辑器:
type | handle | hint | flag | tr | blnd | format | source crop (l,t,r,b) | frame | name
HWC | 557cf6e910 | 0000 | 0000 | 04 | 0100 | ? 00000011 | 0.0, 0.0, 1280.0, 720.0 | 0, 0, 720, 1280 | SurfaceView
FB TARGET | 557cf04f30 | 0000 | 0000 | 00 | 0105 | RGBA_8888 | 0.0, 0.0, 720.0, 1280.0 | 0, 0, 720, 1280 | HWC_FRAMEBUFFER_TARGET
D)仅启用android:id="@+id/frameLayout"
+ android:id="@+id/controls"
+ <ImageView ...
布局;启用相机预览:
$ ./adb shell screenrecord --time-limit 10 --bit-rate 6000000 /storage/sdcard1/demo3.mp4
,结果是视频文件:1280 x 720; H.264 / AVC; 20FPS ;比特率:2879 kbps。
硬件编辑器:
type | handle | hint | flag | tr | blnd | format | source crop (l,t,r,b) | frame | name
HWC | 557cfa2040 | 0000 | 0000 | 04 | 0100 | ? 00000011 | 0.0, 0.0, 1280.0, 720.0 | 0, 0, 720, 1280 | SurfaceView
HWC | 557cfb6be0 | 0000 | 0000 | 00 | 0105 | RGBA_8888 | 590.0, 880.0, 720.0, 1280.0 | 590, 880, 720, 1280 | com.example.test/com.example.test.RecordActivity
FB TARGET | 557cf04f30 | 0000 | 0000 | 00 | 0105 | RGBA_8888 | 0.0, 0.0, 720.0, 1280.0 | 0, 0, 720, 1280 | HWC_FRAMEBUFFER_TARGET
使用systrace
进行测试:
(图像从1.5张图像到高度组合以获取更多信息。)
F)禁用叠加(//controls.bringToFront();
),相机预览,运行录制:
G)启用叠加,在所有视图上禁用Alpha ,相机预览,运行录制:
提醒是关于:
Setting an alpha between 0 and 1 has significant performance costs, if one of the fast alpha paths is not used.
=&gt;对于案例G:我在所有视图上禁用了alpha。警报已删除,但FPS仍为:20。Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn't block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.
=&gt;仍未解决。但有趣的是,因为,当我评论://controls.bringToFront();
(案例F)时,所以controls
布局是在相机预览之后(如果我理解的话),因此位图处理上的alpha仍然执行,但是FPS是:30 =&gt;好。
差异,我从比较案例中看到E / F / G(比例为~5秒):
surfaceFlinger
是App的名称:com。*。pso(这是我的RecordActivity):SurfaceView
图表的项目数相似。/system/bin/surfaceflinger
:command onDraw()
/system/bin/surfaceflinger
从Binder_1
到Binder_5
:dequeueBuffer
<
案例E:切片:~1200的壁持续时间~3500ms,/system/bin/mediaserver
中的IppExecuterThre
中的surfaceflinger
中的情况类似。 dequeueBuffer
因此,从叠加视图中删除alpha会略微提高性能,但不会增加FPS。
答案 0 :(得分:1)
有两个独立的事情发生:
通常情况下,#2可以通过硬件覆盖来完成 - 每一层都传递给显示硬件,当像素被发送到显示器时,显示硬件。对于虚拟显示器,不涉及显示硬件,并且由SurfaceFlinger在GPU上执行合成。
很难说是什么导致了您所看到的效果。可能是应用程序正在放慢速度并且不经常更新,可能是因为虚拟显示开销使GPU陷入无法跟上的程度。如果你只有两层(View和SurfaceView),那么层组合开销不应该那么糟糕。
唯一可以确定的方法是使用systrace来快速捕捉系统的痕迹&#34;和&#34;慢&#34;模式并找出它们的不同之处。
添加:快速查看硬件编辑器中的图层堆栈可能会很有趣,只是为了了解不同配置中的内容。如果你adb shell dumpsys SurfaceFlinger
,你会获得大量的输出;靠近底部的东西看起来像like this。它会告诉你这些图层是什么,它们有多大,以及它们是如何订购的。