Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PhoneMonitor

Вторичный монитор Windows 10/11 на экране Android-устройства через USB.

Система написана с нуля: драйвер косвенного дисплея, приложение-стример и нативный Android-клиент. Сторонних зависимостей нет — только Windows SDK/WDK и платформенные API Android.

Рабочий стол Windows → виртуальный монитор (IddCx) → разделяемая видеопамять
    → аппаратный H.264 → TCP через adb (USB) → MediaCodec → SurfaceView

Статус: v1.0, работает

Версия проверена на реальном железе сквозным прогоном, а не только сборкой.

Стенд: Windows 11 26200, Intel Arc 140T iGPU, кодировщик Intel QuickSync · vivo V2509A, Android 16 (API 36), экран 1216×2640 @ 120 Гц, декодер MediaTek.

Метрика Измерено
Задержка Windows: публикация кадра драйвером → отправка в сокет 10,3 мс средняя, 15,6 мс пик
Кодирование (Intel QuickSync, 1080p) 9,4 мс
Декодирование на телефоне 6–14 мс
Композиция Android при 120 Гц ~8,3 мс
Сквозная оценка ≈26 мс
Потери кадров за прогон (2220 кадров) 0 на передаче, 0 на приёме
Глубина очереди декодера 0–1 пакет

Целевые «менее 30 мс» достигнуты при панели 120 Гц. На 60 Гц следует ожидать ≈34 мс: композиция Android даёт один период панели и является крупнейшим неустранимым слагаемым.

Что работает

  • Драйвер поднимает виртуальный монитор, Windows разбирает сгенерированный EDID и создаёт устройство DISPLAY\PMN0001.
  • Кадры передаются в разделяемой видеопамяти без единой копии через системную.
  • Клиент получает поток, декодирует аппаратно и выводит на SurfaceView.
  • Согласование геометрии, отчёт о нагреве, автоматический adb forward, переподключение после разрыва.

Что не доделано

  1. Активное разрешение не переключается. Драйвер объявляет системе новый список режимов и рапортует об успехе, но Windows оставляет монитор на 1920×1080. На телефон идёт 1080p, растянутый на его экран. Смена списка режимов не равна переключению активного режима — нужен явный SetDisplayConfig.
  2. Гонка при первом назначении swapchain. IddCxSwapChainSetDevice возвращает 0x887A0026, повторное назначение проходит нормально. Внешне незаметно.
  3. Intra-Refresh на Intel QuickSync принимается только как флаг: шаг волны выбирает сам кодировщик. Вариант с явным числом кадров отвергается.

Быстрый старт

Что понадобится

Компонент Зачем
Visual Studio 2022 Build Tools, нагрузка «Разработка классических приложений на C++» компилятор и Windows SDK
Windows Driver Kit той же версии, что SDK только для драйвера
CMake 3.21+ сборка
Android SDK Platform-Tools adb
JDK 17 + Android SDK (или Android Studio) сборка клиента

Прямые ссылки и разбор частых граблей — в docs/BUILD.md.

1. Собрать

cmake -S driver   -B build/driver   -A x64 && cmake --build build/driver   --config Release
cmake -S streamer -B build/streamer -A x64 && cmake --build build/streamer --config Release
cd android-client && .\gradlew.bat assembleDebug

2. Разрешить загрузку самоподписанного драйвера

Это снижает защиту машины. Secure Boot придётся выключить в UEFI, а если включён BitLocker — сначала сохранить ключ восстановления и приостановить защиту, иначе следующая загрузка потребует 48-значный пароль. Подробный безопасный порядок — в docs/BUILD.md, раздел 2.1.

bcdedit /set testsigning on

затем перезагрузка.

Проверить состояние защиты в любой момент:

powershell -NoProfile -ExecutionPolicy Bypass -File tools\check-security.ps1

3. Подписать и установить драйвер

powershell -NoProfile -ExecutionPolicy Bypass -File tools\install-driver.ps1

Скрипт сам запросит права, создаст тестовый сертификат, подпишет пакет, установит его и создаст узел устройства. Вывод дублируется в build\driver-install.log.

Удалить: тот же скрипт с ключом -Remove.

4. Поставить клиент и запустить

adb install -r android-client\app\build\outputs\apk\debug\app-debug.apk

Запустите приложение на телефоне (оно откроет порт 6100 и будет ждать), затем на компьютере:

build\streamer\Release\phonemonitor-streamer.exe

Если adb не в PATH, укажите путь: --adb "C:\путь\к\adb.exe".

Полный список ключей: phonemonitor-streamer.exe --help.


Состав

Каталог Компонент Технологии
driver/ Драйвер косвенного дисплея UMDF 2.0, IddCx 1.10, D3D11.4, C++17
streamer/ Приложение-стример Win32, NVENC / Media Foundation, Winsock, C++17
android-client/ Клиент Kotlin, MediaCodec, SurfaceView, minSdk 26
common/ Общие контракты pm_ipc.h (v4), pm_protocol.h (v1)
tools/ Скрипты установка драйвера, проверка защиты, индикатор прогресса
docs/ Документация архитектура, сборка, диагностика

Ключевые решения

Драйвер не кодирует и не работает с сетью. WUDFHost.exe находится под надзором PnP-менеджера: длительная операция в нём приводит к таймауту старта устройства. Драйвер делает ровно две вещи — отдаёт системе виртуальный монитор и копирует кадры в разделяемую видеопамять.

Кадр не покидает видеопамять на всём пути Windows. Драйвер копирует поверхность swapchain в общую текстуру, стример открывает её на том же адаптере и отдаёт прямо в кодировщик.

Синхронизация ключевым мьютексом, а не фенсом. Исходно проект использовал общий ID3D11Fence с передачей HANDLE через DuplicateHandle. Схема оказалась нерабочей: драйвер живёт под ограниченной учётной записью и получает отказ в доступе при OpenProcess на пользовательский процесс, а обратное направление требует прав администратора. IDXGIKeyedMutex принадлежит самой текстуре, открывается вместе с ней по имени и не требует никаких привилегий.

Разрешение диктует телефон. Клиент первым пакетом сообщает геометрию экрана и предел аппаратного декодера — это разные вещи, и устройства с экраном 2400×1080 нередко имеют декодер до 1920×1080.

Задержка не прячется в буферах. VBV кодировщика — один кадр, SO_SNDBUF — два кадра, очередь декодера — восемь NAL. Большой буфер не устраняет затор, а превращает его в скрытую задержку.

Реакция на нагрев — на первом же сигнале. THERMAL_STATUS_LIGHT включает режим 720p. Ждать жёсткого троттлинга нельзя: из него система не выходит, пока не остынет.


Поддержка кодировщиков

GPU Путь Intra-Refresh
NVIDIA NVENC напрямую (nvEncodeAPI64.dll, динамическая загрузка) полоса 5 % ширины кадра, точный контроль
AMD Media Foundation MFT (официальная обёртка над AMF) через CODECAPI_AVEncVideoGradualIntraRefresh
Intel Media Foundation MFT (QuickSync) принимается флагом, шаг выбирает кодировщик

Диагностика

Где Что смотреть
C:\ProgramData\PhoneMonitor\driver.log журнал драйвера, каждый шаг с меткой времени
build\driver-install.log результат установки драйвера
build\security-status.log состояние BitLocker, Secure Boot, тестовой подписи
вывод стримера сводка каждые N кадров: частота, битрейт, задержка
adb logcat -s PhoneMonitor:V VideoDecoder:V StreamServer:V журнал клиента

Разбор типовых отказов — в docs/BUILD.md, раздел 6.


Язык кода

Все комментарии в исходниках и весь вывод журналов — на русском языке.

About

Вторичный монитор Windows 10/11 на экране Android через USB. Драйвер косвенного дисплея (UMDF 2.0 + IddCx), аппаратное кодирование H.264 (NVENC / Media Foundation) и нативный клиент на MediaCodec. Целевая задержка менее 30 мс.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages