2016-05-30 372 views
0

我想問一下,如果可以通過覆蓋視圖來改善FPS的錄製屏幕。Android mediaProjection + SurfaceView +覆蓋視圖

應用的

僞結構:

1)全屏的FrameLayout在AppCompatActivity:

<?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
攝像頭預覽透支了1倍(紫色)
ImageView的透支了2倍(綠色)
的TextView透支了3倍(粉紅色)

當我能夠在剖析GPU渲染設備上的調試模式:see
我有綠線下的所有酒吧(16毫秒)。

也許我有些東西效率低下。目標是帶有/不帶重疊視圖的相同FPS的記錄屏幕。有可能的?

測試與screenrecord命令和硬件作曲:

A)啓用視圖的覆蓋;啓用相機預覽:
$ ./adb shell screenrecord --time-limit 10 --bit-rate 6000000 /storage/sdcard1/demo3.mp4並且結果是視頻文件:1280 x 720; H.264/AVC; 20FPS;比特率:4585kb/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×720; H.264/AVC; 30FPS;比特率:6684kb/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;比特率:4280kbps。

硬件作曲:

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;比特率:2879kbps。

硬件合成:

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圖像高度結合以獲取更多信息)

E)啓用覆蓋,相機預覽,運行錄音: enter image description here

F)禁用覆蓋(//controls.bringToFront();),相機預覽,運行記錄: enter image description here

G)啓用疊加,禁用阿爾法上所有視圖,相機預覽,運行記錄: enter image description here

提醒是關於:

  • 低效查看字母的用法:Setting an alpha between 0 and 1 has significant performance costs, if one of the fast alpha paths is not used. =>對於案例G:我disa在所有視圖上放出阿爾法。警報被刪除,但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. =>仍未解決。

但有意思的是,因爲,當我的評論://controls.bringToFront();(情況F),所以controls佈局攝像頭預覽後面(如果我沒理解),等位圖處理阿爾法仍在執行,但FPS是:30 =>好。

差異,我是從比較的情況下看到了E/F/G(規模〜5秒):

  • 情況下,F/G:在CPU上的東西的工作:4,5,6,7,案例E不。
  • surfaceFlinger是應用的名字:。com * PSO(這是我的RecordActivity):
    情況E:184項,
    情況下F:312項,
    情況下G:204項。
    對於SurfaceView圖表的項目數量相似。
  • /system/bin/surfaceflinger:命令onDraw()
    方案E:片:〜7000具有壁持續時間:〜3300ms,
    情況下F:片:〜11000具有壁持續時間:〜2300ms,
    情況下G:片:〜7800具有牆持續時間:〜3400ms。
  • /system/bin/surfaceflingerBinder_1Binder_5:命令dequeueBuffer
    方案E:片:〜1200具有壁持續時間〜3500ms,
    情況下F:片:〜2080具有壁持續時間〜38MS,
    情況下G:片:〜 1509有持續時間〜3200ms,
  • in /system/bin/mediaserver in IppExecuterThresurfaceflinger的情況類似。 dequeueBuffer
    方案E:片:282具有壁持續時間〜3600ms,
    情況下F:片:462具有壁持續時間〜117ms,
    情況下G:片:304具有壁持續時間〜3300ms。

因此,從疊加視圖中刪除alpha會輕微提高性能,但不會增加FPS。

+1

如果你使用外部記錄器,比如'screenrecord'命令,你會得到相同的結果嗎?在應用程序以20fps記錄的配置中,當您不*記錄時,您能否確定它是否也以20fps的速度運行? (只是想將幀生成和錄製行爲分開......如果在啓用或不啓用錄製的情況下以20fps運行,則可以從要擔心的一組事物中移除MediaProjection。) – fadden

+0

發佈已更新。(未嘗試啓用錄製功能,因爲FPS速度很慢,通過MediaProjection + MediaMuxer和'screenrecord'命令進行錄製。嘗試使用啓用/禁用覆蓋並啓用相機預覽的運行活動,但未進行錄製。) – t0m

+1

當然,重新在您的特定設備上播放性能牆。錄製屏幕會爲虛擬顯示添加GPU圖層組合,以及視頻編碼本身。在某些設備上,運行'screenrecord'會在基本應用程序上產生顯着差異,而在其他設備上,您甚至不會知道它正在運行。仔細分析systrace痕跡是真正瞭解底層情況的唯一方法。您可能需要檢查HWC配置以查看所有正在組成的內容;我在我的回答中添加了一個註釋,說明在哪裏以及如何查看。 – fadden

回答

1

有兩個獨立的事情在進行:

  1. 視圖的渲染和組成。這發生在單個圖層上,並由應用程序本身執行。
  2. 圖層的渲染和組合。這發生在系統圖形合成器SurfaceFlinger中。

通常情況下#2可以用硬件疊加完成 - 每一層都被傳遞給顯示硬件,當像素髮送到顯示器時,每個層都進行合成。對於虛擬顯示器,不涉及顯示硬件,並由SurfaceFlinger在GPU上執行合成。

很難說什麼會導致你看到的效果。可能是因爲應用程序速度減慢,更新頻率不高,可能是因爲虛擬顯示器的開銷將GPU重新設置到了無法跟上的程度。如果你只有兩個圖層(視圖和SurfaceView),圖層合成開銷不應該那麼差。

唯一可以肯定的方法是使用systrace在「快速」和「慢速」模式下捕捉系統的蹤跡,並找出它們之所以不同的原因。

地址:快速查看Hardware Composer中的圖層堆棧可能很有趣,只是爲了瞭解不同配置下的外觀。如果你adb shell dumpsys SurfaceFlinger你會得到一大堆的輸出;靠近底部將看起來像like this。這會告訴你圖層是什麼,它們有多大,以及它們是如何訂購的。