Мне нужен какой-то способ получить данные экрана и передать их в поверхность / текстуру DX9 в моем приложении и, по крайней мере, отобразить их 25fps в 1600 * 900 разрешение 30 будет лучше.
Я пробовал BitBliting, но даже после этого я на 20fps и после загрузки данных в текстуру и рендеринга, я на 11fps, что далеко позади того, что мне нужно.
GetFrontBufferData исключен.
Вот это что-то о используя Windows Media API, но я не знаком с этим. Пример — сохранение данных прямо в файл, возможно, их можно настроить для предоставления отдельных кадров, но я не нашел достаточно хорошей документации, чтобы попробовать их самостоятельно.
Мой код:
m_memDC.BitBlt(0, 0, m_Rect.Width(),m_Rect.Height(), //m_Rect is area to be captured
&m_dc, m_Rect.left, m_Rect.top, SRCCOPY);
//at 20-25fps after this if I comment out the rest
//DC,HBITMAP setup and memory alloc is done once at the begining
GetDIBits( m_hDc, (HBITMAP)m_hBmp.GetSafeHandle(),
0L, // Start scan line
(DWORD)m_Rect.Height(), // # of scan lines
m_lpData, // LPBYTE
(LPBITMAPINFO)m_bi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // Use RGB for color table
//at 17-20fps
IDirect3DSurface9 *tmp;
m_pImageBuffer[0]->GetSurfaceLevel(0,&tmp); //m_pImageBuffer is Texture of same
//size as bitmap to prevent stretching
hr= D3DXLoadSurfaceFromMemory(tmp,NULL,NULL,
(LPVOID)m_lpData,
D3DFMT_X8R8G8B8,
m_Rect.Width()*4,
NULL,
&r, //SetRect(&r,0,0,m_Rect.Width(),m_Rect.Height();
D3DX_DEFAULT,0);
//12-14fps
IDirect3DSurface9 *frameS;
hr=m_pFrameTexture->GetSurfaceLevel(0,&frameS); // Texture of that is rendered
pd3dDevice->StretchRect(tmp,NULL,frameS,NULL,D3DTEXF_NONE);
//11fps
Я обнаружил, что для 512 * 512 квадратов он работает на 30 кадрах в секунду (для 490 * 450 при 20-25), поэтому я попытался разделить экран, но, похоже, он не работал хорошо.
Если в коде чего-то не хватает, напишите, не голосуйте. Спасибо
Начиная с Windows 8, появляется новый API дублирования рабочего стола это может использоваться для захвата экрана в видеопамяти, включая изменения курсора мыши и какие части экрана фактически изменились или переместились. Это гораздо более производительно, чем любой из подходов GDI или D3D9, и действительно хорошо подходит для таких вещей, как кодирование рабочего стола в видеопоток, поскольку вам никогда не придется извлекать текстуру из памяти графического процессора. Новый API доступен, перечисляя выходные данные DXGI и вызывая DuplicateOutput на экране вы хотите захватить. Затем вы можете ввести цикл, который ожидает обновления экрана и получает каждый кадр по очереди.
Чтобы кодировать кадры в видео, я бы рекомендовал взглянуть на Медиа Фонд. Посмотрите конкретно на Раковина Писатель для самого простого метода кодирования видеокадров. По сути, вам просто нужно обернуть текстуры D3D, которые вы получаете для каждого видеокадра, в объекты IMFSample. Они могут быть переданы непосредственно в приемник. Увидеть MFCreateDXGISurfaceBuffer а также MFCreateVideoSampleFromSurface функции для получения дополнительной информации. Для лучшей производительности, как правило, вы захотите использовать кодек, такой как H.264, который имеет хорошую поддержку аппаратного кодирования (на большинстве машин).
Для полного раскрытия я работаю в команде, которая владеет API дублирования десктопов в Microsoft, и я лично написал приложения, которые захватывают десктоп (и видео, игры и т. Д.) В видеофайл со скоростью 60 кадров в секунду, используя эту технику, а также как много других сценариев. Это также используется для потоковой передачи экрана, удаленной помощи и многого другого в Microsoft.
Если вам не нравится FrontBuffer, попробуйте BackBuffer:
LPDIRECT3DSURFACE9 surface;
surface = GetBackBufferImageSurface(&fmt);
чтобы сохранить его в файл использовать
D3DXSaveSurfaceToFile(filename, D3DXIFF_JPG, surface, NULL, NULL);