c++ - экрана - скачать программу для съемки видео




Самый быстрый способ захвата экрана (8)

Я хочу написать программу screencasting для платформы Windows, но я не уверен, как захватить экран. Единственный метод, который я знаю, - использовать GDI, но мне любопытно, есть ли другие способы обойти это, и если есть, что несет наименьшие издержки? Скорость - приоритет.

Программа screencasting будет предназначена для записи видеороликов, хотя, если это сужает возможности, я по-прежнему открыт для любых других предложений, которые выпадают из этой области. В конце концов, знания не плохие.

Изменить : я наткнулся на эту статью: различные методы для захвата экрана . Он познакомил меня с этим способом Windows Media API и способом DirectX. В Заключении упоминается, что отключение аппаратного ускорения может значительно повысить производительность приложения захвата. Мне любопытно, почему это так. Может ли кто-нибудь заполнить пробелы для меня?

Редактирование : я читал, что программы screencasting, такие как Camtasia, используют свой собственный драйвер захвата. Может ли кто-нибудь дать мне подробное объяснение того, как это работает, и почему оно быстрее? Мне также может понадобиться руководство по реализации чего-то подобного, но я уверен, что в любом случае есть существующая документация.

Кроме того, теперь я знаю, как FRAPS записывает экран. Он перехватывает базовый графический API для чтения из заднего буфера. Насколько я понимаю, это быстрее, чем чтение из переднего буфера, потому что вы читаете из системной памяти, а не из видеопамяти. Вы можете прочитать статью here .


EDIT: я вижу, что это указано в вашей первой ссылке редактирования как «способ GDI». Это по-прежнему достойный способ пойти даже с рекомендациями по производительности на этом сайте, вы можете легко добраться до 30fps, я бы подумал.

Из this комментария (у меня нет опыта в этом, я просто ссылаюсь на кого-то, кто это делает):

HDC hdc = GetDC(NULL); // get the desktop device context
HDC hDest = CreateCompatibleDC(hdc); // create a device context to use yourself

// get the height and width of the screen
int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);

// create a bitmap
HBITMAP hbDesktop = CreateCompatibleBitmap( hdc, width, height);

// use the previously created device context with the bitmap
SelectObject(hDest, hbDesktop);

// copy from the desktop device context to the bitmap device context
// call this once per 'frame'
BitBlt(hDest, 0,0, width, height, hdc, 0, 0, SRCCOPY);

// after the recording is done, release the desktop context you got..
ReleaseDC(NULL, hdc);

// ..and delete the context you created
DeleteDC(hDest);

Я не говорю, что это самый быстрый, но операция BitBlt как правило, очень быстрая, если вы копируете между совместимыми контекстами устройств.

Для справки Open Broadcaster Software реализует нечто вроде этого как часть своего метода "dc_capture" , хотя вместо создания целевого контекста hDest с помощью CreateCompatibleDC они используют IDXGISurface1 , который работает с DirectX 10+. Если поддержки нет, они возвращаются к CreateCompatibleDC .

Чтобы изменить его для использования определенного приложения, вам нужно изменить первую строку на GetDC(game) где game - это дескриптор окна игры, а затем установить правильную height и width окна игры.

Когда у вас есть пиксели в hDest / hbDesktop, вам все равно нужно сохранить его в файл, но если вы делаете захват экрана, я бы подумал, что вы захотите записать определенное количество из них в память и сохранить в видеофайл в кусках, поэтому я не буду указывать на код для сохранения статического изображения на диск.


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

  1. ПОЧЕМУ DX быстрее? в DX (или в мире графики) применяется более зрелый метод, называемый рендерингом двойного буфера, где присутствуют два буфера, при наличии переднего буфера для аппаратного обеспечения, вы также можете отображать другой буфер, а затем после кадра 1 готовый рендеринг, система свопирует в другой буфер (блокирует его для представления на аппаратное обеспечение и освобождает предыдущий буфер), тем самым рентабельность рендеринга значительно улучшается.
  2. ПОЧЕМУ ускорить ускорение аппаратного ускорения? хотя с двойной визуализацией буфера, FPS улучшается, но время для рендеринга все еще ограничено. современное графическое оборудование обычно включает в себя большую оптимизацию во время рендеринга, как правило, как сглаживание, это очень интенсивно вычисляется, если вы не требуете высококачественной графики, конечно, вы можете просто отключить эту опцию. и это сэкономит вам некоторое время.

Я думаю, что вам действительно нужна система воспроизведения, и я полностью согласен с тем, что обсуждали люди.


Для C ++ вы можете использовать: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
Это может не работать на всех типах 3D-приложений / видео приложений. Тогда эта ссылка может быть более полезной, поскольку она описывает 3 разных метода, которые вы можете использовать.

Старый ответ (C #):
Вы можете использовать System.Drawing.Graphics.Copy , но это не очень быстро.

Пример проекта, который я написал, выполнял именно это: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/

Я планирую обновить этот пример, используя более быстрый метод, например Direct3D: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/

И вот ссылка для захвата видео: как захватить экран для видео с помощью C # .Net?


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

Почему RDP так быстро по сравнению с другим программным обеспечением для дистанционного управления?

Также очевидно, что некоторые свертки StretchRect быстрее, чем BitBlt

http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193

И тот, который вы упомянули (fraps, подключающийся к dll D3D), вероятно, является единственным способом для приложений D3D, но не будет работать с захватом рабочего стола Windows XP. Так что теперь я просто хочу, чтобы на обычных окнах для настольных компьютеров была похожая на фреймы скорость ... кто-нибудь?

(Я думаю, что с помощью aero вы могли бы использовать крючки с фреймами, но пользователям XP было бы не повезло).

Также, по-видимому, изменение глубины битов экрана и / или отключение аппаратного ускорения. может помочь (и / или отключить aero).

https://github.com/rdp/screen-capture-recorder-program включает в себя достаточно быструю утилиту захвата на основе BitBlt и бенчмаркер как часть своей установки, которая позволяет вам оценивать скорости BitBlt для их оптимизации.

VirtualDub также имеет модуль захвата экрана «opengl», который, как говорят, работает быстро и выполняет такие функции, как обнаружение изменений http://www.virtualdub.org/blog/pivot/entry.php?id=290


Я использую d3d9 для получения backbuffer и сохраняю его в png-файле, используя библиотеку d3dx:

    IDirect3DSurface9 *surface ;

    // GetBackBuffer
    idirect3ddevice9->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &surface ) ;

    // save the surface
    D3DXSaveSurfaceToFileA( "filename.png", D3DXIFF_PNG, surface, NULL, NULL ) ;

    SAFE_RELEASE( surface ) ;

Для этого вы должны создать свой swapbuffer с помощью

d3dpps.SwapEffect = D3DSWAPEFFECT_COPY ; // for screenshots.

(Таким образом, вы гарантируете, что бэкбуффер не искалечен, прежде чем снимать скриншот).


Я написал класс, который реализовал метод GDI для захвата экрана. Мне тоже нужна дополнительная скорость, поэтому, после обнаружения метода DirectX (через GetFrontBuffer), я попробовал это, ожидая, что он будет быстрее.

Я был встревожен, обнаружив, что GDI работает примерно в 2,5 раза быстрее. После 100 пробных снимков, на которых был показан мой монитор с двумя мониторами, реализация GDI составляла в среднем 0,65 с за захват экрана, тогда как метод DirectX составлял в среднем 1,72 с. Таким образом, GDI определенно быстрее, чем GetFrontBuffer, согласно моим тестам.

Мне не удалось получить код Brandrew для тестирования DirectX через GetRenderTargetData. Экранная копия получилась чисто черной. Тем не менее, он может быстро скопировать этот пустой экран! Я продолжу заниматься этим и надеюсь получить рабочую версию, чтобы увидеть реальные результаты.


Я понимаю, что следующее предложение не отвечает на ваш вопрос, но самый простой метод, который я нашел для захвата быстро меняющегося представления DirectX, заключается в подключении видеокамеры к порту S-video видеокарты и записи изображений в виде фильм. Затем переместите видео с камеры обратно в файл MPG, WMV, AVI и т. Д. На компьютере.


я сам делаю это с directx и думаю, что это так быстро, как вы хотели бы этого. У меня нет быстрого кода, но я нашел this что должно быть полезно. версия directx11 не должна сильно отличаться, directx9 может быть немного больше, но это путь





windows