Я хочу написать программу для экрана для платформы Windows, но не знаю, как сделать снимок экрана. Единственный известный мне метод - это использовать GDI, но мне любопытно, есть ли другие способы сделать это, и, если есть, то какие издержки наименьшие? Скорость является приоритетом.
Программа для создания скринкастинга будет предназначена для записи игровых материалов, хотя, если это сузит варианты, я по-прежнему открыт для любых других предложений, которые выпадают из этой области. Знание не плохо, в конце концов.
Редактировать : я наткнулся на эту статью: Различные методы захвата экрана . Он познакомил меня с методикой Windows Media API и DirectX. В заключении упоминается, что отключение аппаратного ускорения может значительно повысить производительность приложения захвата. Мне любопытно, почему это так. Может ли кто-нибудь заполнить пропущенные для меня пробелы?
Редактировать : я читал, что такие программы, как Camtasia, используют собственный драйвер захвата. Может ли кто-нибудь дать мне подробное объяснение того, как это работает, и почему это быстрее? Мне также может понадобиться руководство по реализации чего-то подобного, но я уверен, что в любом случае существует документация.
Кроме того, теперь я знаю, как FRAPS записывает экран. Он перехватывает базовый графический API для чтения из заднего буфера. Из того, что я понимаю, это быстрее, чем чтение из переднего буфера, потому что вы читаете из системной памяти, а не видео-памяти. Вы можете прочитать статью здесь .
MovePlayerLeft()
. И вы также записываете время и продолжительность нажатия клавиш и другой ввод. Затем, когда вы находитесь в режиме воспроизведения, вы просто игнорируете ввод и вместо этого читаете записанные данные. Если в данных вы видите нажатие левой клавиши, вы звонитеMovePlayerLeft()
.Ответы:
Это то, что я использую, чтобы собирать отдельные кадры, но если вы измените это и будете постоянно держать две цели открытыми, то вы можете «передать» их на диск, используя статический счетчик для имени файла. - Я не могу вспомнить, где я нашел это, но это было изменено, спасибо кому бы то ни было!
источник
РЕДАКТИРОВАТЬ: я вижу, что это указано в вашей первой ссылке на редактирование как «путь GDI». Это по-прежнему достойный способ, даже если учесть рекомендации по производительности на этом сайте, я думаю, вы можете легко получить 30fps.
Из этого комментария (у меня нет опыта в этом, я просто ссылаюсь на кого-то, кто делает):
Я не говорю, что это самый быстрый, но
BitBlt
операция обычно очень быстрая, если вы копируете между контекстами совместимого устройства.Для справки, Open Broadcaster Software реализует что-то вроде этого как часть своего метода "dc_capture" , хотя вместо создания контекста назначения
hDest
с использованиемCreateCompatibleDC
они используютIDXGISurface1
, который работает с DirectX 10+. Если нет поддержки для этого, они отступаютCreateCompatibleDC
.Чтобы изменить его на использование определенного приложения, вам нужно изменить в первой строке,
GetDC(game)
гдеgame
находится дескриптор окна игры, а затем установить правоheight
иwidth
окно игры тоже.Если у вас есть пиксели в hDest / hbDesktop, вам все равно нужно сохранить их в файл, но если вы делаете снимок экрана, то я подумаю, что вы захотите сохранить определенное количество их в памяти и сохранить в видеофайл в кусках, поэтому я не буду указывать на код для сохранения статического образа на диск.
источник
Я написал программное обеспечение для захвата видео, похожее на FRAPS для приложений DirectX. Исходный код доступен, и моя статья объясняет общую технику. Посмотрите на http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/
Уважение к вашим вопросам, связанным с производительностью,
DirectX должен быть быстрее, чем GDI, за исключением случаев, когда вы читаете из фронтбуфера, который очень медленный. Мой подход похож на FRAPS (чтение из буфера). Я перехватываю множество методов из интерфейсов Direct3D.
Для записи видео в реальном времени (с минимальным воздействием на приложение) необходим быстрый кодек. FRAPS использует собственный видеокодек без потерь. Lagarith и HUFFYUV - это универсальные видеокодеки без потерь, разработанные для приложений реального времени. Вы должны посмотреть на них, если вы хотите выводить видео файлы.
Другим подходом к записи скринкастов может быть написание Зеркального драйвера. Согласно Википедии: Когда видео зеркалирование активно, каждый раз, когда система обращается к основному видеоустройству в месте внутри зеркальной области, копия операции рисования выполняется на зеркальном видеоустройстве в режиме реального времени. См. Зеркальные драйверы на веб-сайте MSDN: http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx .
источник
Я использую d3d9 для получения буфера и сохраняю его в png-файл, используя библиотеку d3dx:
Для этого вы должны создать свой swapbuffer с
(Таким образом, вы гарантируете, что задний буфер не будет поврежден до того, как вы сделаете скриншот).
источник
GetRenderTarget
есть?По моему мнению, подход GDI и подход DX различны по своей природе. рисование с использованием GDI применяет метод FLUSH, подход FLUSH рисует кадр, затем очищает его и перерисовывает другой кадр в том же буфере, это приведет к мерцанию в играх, требующих высокой частоты кадров.
Я думаю, что вам действительно нужна система воспроизведения, я полностью согласен с тем, что обсуждали люди.
источник
Я написал класс, который реализовал метод GDI для захвата экрана. Я тоже хотел получить дополнительную скорость, поэтому, после обнаружения метода DirectX (через GetFrontBuffer), я попробовал это, ожидая, что он будет быстрее.
Я был встревожен, обнаружив, что GDI работает примерно в 2,5 раза быстрее. После 100 испытаний захвата моего дисплея с двумя мониторами реализация GDI в среднем составляла 0,65 с на каждый снимок экрана, а метод DirectX - 1,72 с. Так что, согласно моим тестам, GDI определенно быстрее, чем GetFrontBuffer.
Мне не удалось заставить код Brandrew работать для тестирования DirectX через GetRenderTargetData. Экранная копия вышла чисто черной. Тем не менее, он может скопировать этот пустой экран очень быстро! Я продолжу возиться с этим и надеюсь получить рабочую версию, чтобы увидеть реальные результаты.
источник
GetRenderTargetData
подход работает. Может быть, я напишу свой собственный ответ, когда я закончу свое заявление. Или вы можете обновить свой, как только у вас все заработало.Несколько вещей, которые я смог найти: очевидно, использование «зеркального драйвера» быстро, хотя я не знаю об OSS.
Почему RDP такой быстрый по сравнению с другими программами дистанционного управления?
Также очевидно, что использование некоторых сверток StretchRect быстрее, чем BitBlt
http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193
И тот, который вы упомянули (подключение Fraps к D3D DLL), вероятно, является единственным способом для приложений D3D, но не будет работать с захватом рабочего стола Windows XP. Так что теперь я просто хотел бы, чтобы по обычным окнам рабочего стола был эквивалентный по скорости Fraps ... кто-нибудь?
(Я думаю, что с aero вы можете использовать хрипы, похожие на fraps, но пользователям XP не повезет).
Также очевидно изменение битовой глубины экрана и / или отключение аппаратного ускорения. может помочь (и / или отключить аэро).
https://github.com/rdp/screen-capture-recorder-program включает в себя достаточно быструю утилиту захвата на основе BitBlt и тестовый модуль в составе его установки, который позволяет вам измерять скорости BitBlt для их оптимизации.
VirtualDub также имеет модуль захвата экрана «opengl», который, как говорят, быстр и делает такие вещи, как обнаружение изменений http://www.virtualdub.org/blog/pivot/entry.php?id=290
источник
Для 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?
источник
В Windows 8 Microsoft представила API дублирования рабочего стола Windows. Это официально рекомендуемый способ сделать это. Одна из приятных особенностей, которую он имеет для экранного вещания, заключается в том, что он обнаруживает движение окна, поэтому вы можете передавать дельты блоков при перемещении окон вместо необработанных пикселей. Кроме того, он сообщает вам, какие прямоугольники изменились, от одного кадра к другому.
Пример кода Microsoft довольно сложный, но API на самом деле прост и удобен в использовании. Я собрал пример проекта, который намного проще официального примера:
https://github.com/bmharper/WindowsDesktopDuplicationSample
Документы: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api.
Официальный пример кода Microsoft: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a
источник
Вы можете попробовать проект с открытым исходным кодом c ++ WinRobot @git , мощный скриншот
Служба поддержки :
источник
Я сам делаю это с Directx и думаю, что это так быстро, как вы бы этого хотели. у меня нет быстрого примера кода, но я нашел это, что должно быть полезно. версия для DirectX11 не должна сильно отличаться, возможно, DirectX9 немного больше, но это путь
источник
Я понимаю, что следующее предложение не отвечает на ваш вопрос, но самый простой метод, который я нашел для захвата быстро меняющегося представления DirectX, это подключить видеокамеру к порту S-video видеокарты и записать изображения как фильм. Затем перенесите видео с камеры обратно в файл MPG, WMV, AVI и т. Д. На компьютере.
источник
Запись экрана может быть сделана в C # с использованием VLC API . Я сделал пример программы, чтобы продемонстрировать это. Он использует библиотеки LibVLCSharp и VideoLAN.LibVLC.Windows . Вы можете получить гораздо больше функций, связанных с рендерингом видео, используя этот кроссплатформенный API.
Документацию по API см .: LibVLCSharp API Github.
источник
DXGI Desktop Capture
Проект, который захватывает изображение рабочего стола с дублированием DXGI. Сохраняет захваченное изображение в файл в различных графических форматах (* .bmp; * .jpg; * .tif).
Этот образец написан на C ++. Вам также нужен некоторый опыт работы с DirectX (D3D11, D2D1).
Что может сделать приложение
источник