Напишите RDP-клиент, который выводит пиксели экрана

Я хотел бы реализовать клиент RDP в C++ который может получить значение цвета всех пикселей экрана и вывести их в файл. Я знаю, что это концептуально отличается от того, как работает RDP, но мне это нужно для моего приложения. Я пытаюсь использовать freerdp, но я не уверен, как эффективно написать клиент, который просто сбрасывает все пиксели в файле.

Пока что моя лучшая попытка - использовать функцию gdi_GetPixel_32bpp но, конечно, вызов этой функции для каждого пикселя по очереди далеко не эффективен.

Решение, которое использует другую библиотеку, также будет высоко ценится.

4 ответа

Это должно быть довольно легко сделать очень эффективным способом, используя libfreerdp-gdi. FreeRDP может рендерить все в программный буфер, который вы затем можете записать в файл, и вы можете сделать это полностью в памяти, без среды X11, если хотите. Поскольку Linux упоминается, одним из быстрых способов начать работу было бы использование xfreerdp с параметром /gdi:sw для использования libfreerdp-gdi (по умолчанию используется реализация на основе X11), а затем выгрузка пикселей в качестве обновлений. Заходите. Вы можете подключиться к xf_sw_end_paint, который вызывается в конце массива обновлений. У вас есть доступ к неверному региону и пиксельному буферу (все в структуре rdpGdi* gdi). Важными полями являются gdi->primary_buffer, gdi->dstBpp, gdi->bytesPerPixel, gdi->width и gdi->height. В большинстве случаев вы получите буфер XRGB32, с которым легко иметь дело. В случае сомнений, посмотрите на gdi_init() для инициализации внутреннего буфера.

Ну, вы можете попробовать это (отказ от проверки непроверенного псевдокода):

HGDI_DC memDC = gdi_CreateCompatibleDC ( hDC );
HGDI_BITMAP memBM = gdi_CreateCompatibleBitmap ( hDC, screenWidth, screenHeight );
gdi_SelectObject ( memDC, memBM );
gdi_BitBlt(memDC, 0, 0, screenWidth, screenHeight, hDC, 0, 0, GDI_SRCCOPY);

Теперь вы должны иметь в memBM->data полный массив данных пикселей. memBM->data имеет следующий размер: memBM->width * memBM->height * memBM->bytesPerPixel

Надеюсь, что это поможет вам хотя бы в некоторой степени.

Если вы запускаете сервер VNC X и запускаете на нем полноэкранный клиент RDP (без оконного менеджера и т. Д.), Последовательность рисования должна выглядеть примерно так:

  1. RDP-клиент получает обновление от удаленного сеанса
  2. RDP-клиент преобразует обновление в сообщения X11, скорее всего, отправленные через транспорт с общей памятью
  3. VNC-сервер получает запросы X11 и использует их для отображения растрового изображения

поэтому накладные расходы должны быть просто протоколом X11, который по общему признанию неуклюж, но должен по крайней мере передаваться через сегмент совместно используемой памяти.

Честно говоря, я сначала попробую этот подход с нулевым кодированием и посмотрим, действительно ли проблема в производительности.

WebRTC может иметь некоторый код, на который вы можете посмотреть, чтобы помочь, например, захват экрана или захват окна.

Захват рабочего стола более сложен, потому что он (1) выполняет различие, чтобы захватить минимальное содержимое, и (2) также захватывает мышь. Поскольку рабочий стол - это просто специальное "окно", как ::GetDesktopWindow(), И его DC можно получить с помощью этого окна или просто GetDC(NULL)Вы можете использовать средство захвата окна и игнорировать более сложные биты. Проверьте функцию захвата оконного захвата для деталей, а также некоторые полезные советы по обработке Aero и другие вопросы композитинга / за кадром.

Другие вопросы по тегам