Chcę napisać program do wyświetlania ekranu dla platformy Windows, ale nie jestem pewien, jak zrobić zrzut ekranu. Jedyną metodą, o której wiem, jest użycie GDI, ale jestem ciekawy, czy istnieją inne sposoby, aby to zrobić, a jeśli tak, to który generuje najmniejsze koszty? Szybkość jest priorytetem.
Program do wyświetlania ekranu będzie służył do nagrywania materiału z gry, chociaż jeśli to zawęzi opcje, nadal jestem otwarty na wszelkie inne sugestie, które wykraczają poza ten zakres. W końcu wiedza nie jest zła.
Edycja : natknąłem się na ten artykuł: Różne metody przechwytywania ekranu . Wprowadził mnie w sposób robienia tego w Windows Media API i DirectX. We wniosku wspomniano, że wyłączenie akceleracji sprzętowej może drastycznie poprawić wydajność aplikacji przechwytującej. Ciekaw jestem, dlaczego tak jest. Czy ktoś mógłby wypełnić dla mnie brakujące pola?
Edycja : Czytałem, że programy do wyświetlania ekranu, takie jak Camtasia, używają własnego sterownika przechwytywania. Czy ktoś mógłby mi szczegółowo wyjaśnić, jak to działa i dlaczego jest szybsze? Mogę też potrzebować wskazówek dotyczących implementacji czegoś takiego, ale jestem pewien, że i tak istnieje dokumentacja.
Poza tym wiem teraz, jak FRAPS nagrywa ekran. Przechwytuje podstawowy interfejs API grafiki w celu odczytu z bufora tylnego. Z tego, co rozumiem, jest to szybsze niż odczyt z przedniego bufora, ponieważ czytasz z systemowej pamięci RAM, a nie z pamięci RAM wideo. Możesz przeczytać artykuł tutaj .
MovePlayerLeft()
. Ponadto rejestrujesz czas i czas trwania naciśnięć klawiszy i innych danych wejściowych. Następnie, gdy jesteś w trybie odtwarzania, po prostu ignorujesz dane wejściowe i zamiast tego odczytujesz zapisane dane. Jeśli w danych widać naciśnięcie lewego klawisza, dzwoniszMovePlayerLeft()
.Odpowiedzi:
To jest to, czego używam do zbierania pojedynczych ramek, ale jeśli zmodyfikujesz to i pozostawisz oba cele otwarte przez cały czas, możesz „przesłać” to na dysk używając statycznego licznika dla nazwy pliku. - Nie pamiętam, gdzie to znalazłem, ale dzięki komukolwiek zostało to zmodyfikowane!
źródło
EDYCJA: Widzę, że jest to wymienione pod Twoim pierwszym linkiem edycji jako „sposób GDI”. To wciąż przyzwoity sposób, nawet z poradami dotyczącymi wydajności na tej stronie, wydaje mi się, że można łatwo uzyskać 30 klatek na sekundę.
Z tego komentarza (nie mam doświadczenia w tym, odnoszę się tylko do kogoś, kto to robi):
Nie mówię, że jest to najszybsze, ale
BitBlt
operacja jest ogólnie bardzo szybka, jeśli kopiujesz między kompatybilnymi kontekstami urządzeń.Dla porównania, Open Broadcaster Software implementuje coś takiego jako część swojej metody „dc_capture” , chociaż zamiast tworzyć kontekst docelowy
hDest
za pomocąCreateCompatibleDC
, używa znakuIDXGISurface1
, który działa z DirectX 10+. Jeśli nie ma dla tego wsparcia, wracają doCreateCompatibleDC
.Aby to zmienić, aby korzystać z aplikacji specyficzne, trzeba zmienić pierwszej linii
GetDC(game)
, gdziegame
jest uchwytem okna gry, a następnie ustawić prawoheight
iwidth
okna w grze zbyt.Gdy masz piksele w hDest / hbDesktop, nadal musisz zapisać je do pliku, ale jeśli robisz zrzut ekranu, to pomyślałem, że chciałbyś buforować pewną ich liczbę w pamięci i zapisać w pliku wideo fragmentami, więc nie będę wskazywał na kod do zapisywania statycznego obrazu na dysku.
źródło
Napisałem oprogramowanie do przechwytywania wideo, podobne do FRAPS dla aplikacji DirectX. Kod źródłowy jest dostępny, a mój artykuł wyjaśnia ogólną technikę. Zajrzyj na http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/
Szanuj Twoje pytania dotyczące wydajności,
DirectX powinien być szybszy niż GDI, z wyjątkiem sytuacji, gdy czytasz z przedniego bufora, który jest bardzo wolny. Moje podejście jest podobne do FRAPS (czytanie z bufora wstecznego). Przechwytuję zestaw metod z interfejsów Direct3D.
Do nagrywania wideo w czasie rzeczywistym (przy minimalnym wpływie aplikacji) niezbędny jest szybki kodek. FRAPS używa własnego bezstratnego kodeka wideo. Lagarith i HUFFYUV to ogólne bezstratne kodeki wideo przeznaczone do zastosowań w czasie rzeczywistym. Powinieneś spojrzeć na nie, jeśli chcesz wyprowadzić pliki wideo.
Innym podejściem do nagrywania screencastów może być napisanie Mirror Driver. Według Wikipedii: gdy dublowanie wideo jest aktywne, za każdym razem, gdy system rysuje do głównego urządzenia wideo w lokalizacji wewnątrz obszaru lustrzanego, kopia operacji rysowania jest wykonywana na lustrzanym urządzeniu wideo w czasie rzeczywistym. Zobacz sterowniki lustrzane w witrynie MSDN: http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx .
źródło
Używam d3d9 do uzyskania bufora wstecznego i zapisuję go do pliku png za pomocą biblioteki d3dx:
Aby to zrobić, powinieneś stworzyć swój swapbuffer z
(Więc gwarantujesz, że bufor wsteczny nie zostanie uszkodzony przed zrobieniem zrzutu ekranu).
źródło
GetRenderTarget
jest?W moim Impression, podejście GDI i podejście DX mają inny charakter. malowanie za pomocą GDI stosuje metodę FLUSH, podejście FLUSH rysuje ramkę, a następnie ją czyści i przerysowuje kolejną klatkę w tym samym buforze, co spowoduje migotanie w grach wymagających dużej liczby klatek na sekundę.
Myślę, że to, czego naprawdę potrzebujesz, to system powtórek, który całkowicie zgadzam się z tym, o czym rozmawiali ludzie.
źródło
Napisałem klasę, która zaimplementowała metodę GDI do przechwytywania ekranu. Ja też chciałem dodatkowej szybkości, więc po odkryciu metody DirectX (przez GetFrontBuffer) spróbowałem tego, spodziewając się, że będzie szybsza.
Byłem przerażony, gdy stwierdziłem, że GDI działa około 2,5x szybciej. Po 100 próbach przechwytywania mojego wyświetlacza z dwoma monitorami implementacja GDI wynosiła średnio 0,65 s na zrzut ekranu, podczas gdy metoda DirectX średnio 1,72 s. Tak więc GDI jest zdecydowanie szybsze niż GetFrontBuffer, według moich testów.
Nie udało mi się uruchomić kodu Brandrew w celu przetestowania DirectX przez GetRenderTargetData. Kopia ekranowa wyszła całkowicie czarna. Jednak może bardzo szybko skopiować ten pusty ekran! Będę majstrować przy tym i mam nadzieję, że uzyskam działającą wersję, aby zobaczyć prawdziwe wyniki.
źródło
GetRenderTargetData
podejście działa. Może napiszę własną odpowiedź, kiedy skończę aplikację. Lub możesz zaktualizować swoją, gdy wszystko już działa.Kilka rzeczy, które udało mi się zebrać: najwyraźniej użycie „sterownika lustrzanego” jest szybkie, chociaż nie znam sterownika OSS.
Dlaczego RDP jest tak szybki w porównaniu z innymi programami do zdalnego sterowania?
Wygląda na to, że niektóre zwoje StretchRect są szybsze niż BitBlt
http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193
A ten, o którym wspomniałeś (fraps podpina się do dll D3D) jest prawdopodobnie jedynym sposobem dla aplikacji D3D, ale nie będzie działał z przechwytywaniem pulpitu Windows XP. Więc teraz żałuję, że nie było odpowiednika szybkości fraps dla normalnych okien pulpitu ... ktoś?
(Myślę, że z aerodynamiką możesz użyć haczyków podobnych do fraps, ale użytkownicy XP nie mieliby szczęścia).
Najwyraźniej zmienia się także głębia bitowa ekranu i / lub wyłącza przyspieszenie sprzętowe. może pomóc (i / lub wyłączenie aero).
https://github.com/rdp/screen-capture-recorder-program zawiera dość szybkie narzędzie do przechwytywania oparte na BitBlt oraz test porównawczy jako część swojej instalacji, który może pozwolić ci porównać prędkości BitBlt w celu ich optymalizacji.
VirtualDub ma również moduł do przechwytywania ekranu „opengl”, o którym mówi się, że jest szybki i robi takie rzeczy, jak wykrywanie zmian http://www.virtualdub.org/blog/pivot/entry.php?id=290
źródło
W przypadku C ++ możesz użyć: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
Może to nie działać we wszystkich typach aplikacji 3D / aplikacji wideo. Wtedy ten link może być bardziej przydatny, ponieważ opisuje 3 różne metody, których możesz użyć.
Stara odpowiedź (C #):
Możesz użyć System.Drawing.Graphics.Copy , ale nie jest to bardzo szybkie.
Przykładowy projekt, który napisałem robiąc dokładnie to: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/
Planuję zaktualizować ten przykład przy użyciu szybszej metody, takiej jak Direct3D: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/
A oto link do przechwytywania do wideo: Jak przechwycić ekran do wideo przy użyciu C # .Net?
źródło
Wraz z systemem Windows 8 firma Microsoft wprowadziła interfejs Windows Desktop Duplication API. To jest oficjalnie zalecany sposób robienia tego. Jedną z fajnych funkcji, które ma do wyświetlania ekranu, jest to, że wykrywa ruch okna, dzięki czemu można przesyłać delty blokowe, gdy okna są poruszane, zamiast surowych pikseli. Informuje również, które prostokąty uległy zmianie, z jednej klatki do następnej.
Przykładowy kod firmy Microsoft jest dość złożony, ale interfejs API jest w rzeczywistości prosty i łatwy w użyciu. Przygotowałem przykładowy projekt, który jest znacznie prostszy niż oficjalny przykład:
https://github.com/bmharper/WindowsDesktopDuplicationSample
Dokumenty: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api
Oficjalny przykładowy kod Microsoft: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a
źródło
Możesz wypróbować projekt open source C ++ WinRobot @git , potężny program do przechwytywania ekranu
Wsparcie :
źródło
Sam robię to z DirectX i myślę, że jest tak szybki, jak byś chciał. nie mam szybkiego przykładu kodu, ale znalazłem to, co powinno być przydatne. wersja directx11 nie powinna się zbytnio różnić, directx9 może trochę bardziej, ale to jest droga
źródło
Zdaję sobie sprawę, że poniższa sugestia nie odpowiada na twoje pytanie, ale najprostszą metodą, jaką znalazłem, aby uchwycić szybko zmieniający się widok DirectX, jest podłączenie kamery wideo do portu S-video karty graficznej i nagrywanie obrazów jako film. Następnie przenieś wideo z kamery z powrotem do pliku MPG, WMV, AVI itp. Na komputerze.
źródło
Nagrywanie ekranu można wykonać w C # przy użyciu VLC API . Zrobiłem przykładowy program, aby to zademonstrować. Korzysta z bibliotek LibVLCSharp i VideoLAN.LibVLC.Windows . Dzięki temu wieloplatformowemu interfejsowi API można osiągnąć wiele innych funkcji związanych z renderowaniem wideo.
Aby zapoznać się z dokumentacją API, zobacz: LibVLCSharp API Github
źródło
Przechwytywanie pulpitu DXGI
Projekt, który przechwytuje obraz pulpitu z powieleniem DXGI. Zapisuje przechwycony obraz do pliku w różnych formatach obrazu (* .bmp; * .jpg; * .tif).
Ten przykład jest napisany w C ++. Potrzebujesz także doświadczenia z DirectX (D3D11, D2D1).
Co potrafi aplikacja
źródło