2016-05-30 1 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 to 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.

ИЛИ

Когда я отключить CameraPreview видео имеет ~ 30к, но без камеры предварительного просмотра.

Проблема может быть, вероятно, с оверлейными видами. Когда я включить овердрафт в режиме отладки на устройстве: see
камера предварительного просмотра овердрафт 1x (фиолетовый)
ImageView является овердрафт 2x (зеленый)
TextView является овердрафт 3x (розовый)

Когда я включаю профилирования GPU Rendering в режим отладки на устройстве: see
У меня есть все бары под зеленой линией (16 мс).

Возможно, у меня что-то неэффективное. Цель - это экран записи с тем же FPS с/без просмотра наложения. Возможно?

Тесты с screenrecord команды и Hardware Composer:

A) включен просмотров накладкой; включенный просмотр камеры:
$ ./adb shell screenrecord --time-limit 10 --bit-rate 6000000 /storage/sdcard1/demo3.mp4 и результат видеофайл: 1280 x 720; H.264/AVC; 20FPS; Битовая скорость: 4585 кбит/с.

Hardware Composer:

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; битрейт: 6684 кб/с.

Оборудование Композитор:

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 

С) включен только 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 кбит/с.

Оборудование Композитор:

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 кбит/с.

Hardware Composer:

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: i disa bled 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. => еще не решена.

Но это интересно, потому что, когда я комментарий: //controls.bringToFront(); (случай F), так controls расположение позади камеры предварительного просмотра (если я понимаю), так что альфа по обработке растровых изображений по-прежнему выполняться, но FPS составляет: 30 => хорошо.

Различия, что я видел из сравнения случая E/F/G (масштаб ~ 5 секунд):

  • случай F/G: что-то работа на процессорах: 4,5,6,7, ситуационные E нет.
  • в surfaceFlinger это имя приложения:.. Ком * ПСО (это мой RecordActivity):
    случай E: 184 пунктов,
    случай F: 312 пунктов,
    случай G: 204 пунктов.
    Количество элементов аналогично для SurfaceView graph.
  • в /system/bin/surfaceflinger: команда onDraw()
    Случай E: ломтик: ~ 7000 имеет продолжительность стены: ~ 3300ms,
    случая F: ломтик: ~ 11 000 имеет продолжительность стены: ~ 2300ms,
    случая G: ломтик: ~ 7800 имеет Продолжительность стены: ~ 3400 мс.
  • в /system/bin/surfaceflinger от Binder_1 к Binder_5: командам dequeueBuffer
    Случай E: дольки: ~ 1200 имеет продолжительность стенки ~ 3500ms,
    случая F: ломтик: ~ 2080 имеет продолжительность стенки ~ 38ms,
    регистра G: ломтики: ~ 1509 имеет длину стены ~ 3200 мс,
  • в /system/bin/mediaserver в IppExecuterThre аналогичная ситуация, как в surfaceflinger. dequeueBuffer
    Случай Е: ломтики: 282 имеет продолжительность стенки ~ 3600ms,
    Случай F: ломтиков: 462 имеет продолжительность стенки ~ 117ms,
    случае О: ломтиков: 304 имеет продолжительность стенки ~ 3300ms.

Так что удалите альфа из оверлейного обзора, слегка улучшите производительность, но не увеличивайте FPS.

+1

Если вы используете внешний рекордер, например команду 'screenrecord', вы получаете те же результаты? В конфигурации, где приложение записывает со скоростью 20 кадров в секунду, можете ли вы определить, работает ли он при скорости 20 кадров в секунду при записи * не *? (Просто хочу отделить генерацию кадров от поведения записи ... если она работает со скоростью 20 кадров в секунду с включенной или без записи, вы можете удалить MediaProjection из множества вещей, о которых нужно беспокоиться.) – fadden

+0

Сообщение обновлено.(Не пробовали с включенной записью, потому что FPS был очень медленным, с записью через MediaProjection + MediaMuxer и командой 'screenrecord'. Пробовал работать с включенным/отключенным наложением и включенным предварительным просмотром камеры, но без записи.) – t0m

+1

Это, безусловно, повторное нажатие рабочей стены на вашем конкретном устройстве. Запись экрана добавляет композицию слоя графического процессора для виртуального дисплея, а также собственную кодировку видео. На некоторых устройствах запуск «screenrecord» делает заметную разницу в базовых приложениях, а на других вы даже не знаете, что он работает. Тщательный анализ трассировки systrace - это единственный способ действительно увидеть, что происходит под капотом. Вы можете проверить конфигурацию HWC, чтобы увидеть, что все готово; Я добавил примечание к моему ответу о том, где и как смотреть. – fadden

ответ

1

Есть два независимые вещи происходят:

  1. Рендеринг и композиция взглядов. Это происходит на одном уровне и выполняется самим приложением.
  2. Отрисовка и состав слоев. Это происходит в SurfaceFlinger, системном графическом компоновщике.

Обычно # 2 можно выполнять с помощью аппаратных накладок - каждый уровень передается на экранное оборудование, что делает композицию, поскольку пиксели отправляются на дисплей. Для виртуального дисплея нет оборудования для отображения, и композиция выполняется на графическом процессоре SurfaceFlinger.

Трудно сказать, что вызывает эффекты, которые вы видите. Может случиться так, что приложение замедляется и обновляется реже, может быть, что накладные расходы виртуального дисплея облагают GPU до такой степени, что он больше не может идти в ногу. Если у вас есть только два слоя (View и SurfaceView), накладные расходы слоя должны быть не такими уж плохими.

Единственный способ узнать наверняка - использовать systrace, чтобы зафиксировать следы системы в режимах «быстрого» и «медленного» и выяснить, почему они отличаются.

Добавить: Быстрый просмотр стека слоев в Hardware Composer может быть интересным, просто чтобы посмотреть, как все выглядит в разных конфигурациях. Если вы adb shell dumpsys SurfaceFlinger, вы получите большую кучу выхода; рядом с дном будет что-то, что выглядит like this. Это скажет вам, что такое слои, насколько они велики и как они упорядочены.