Windows 플랫폼 용 스크린 캐스팅 프로그램을 작성하고 싶지만 화면을 캡처하는 방법을 잘 모르겠습니다. 내가 아는 유일한 방법은 GDI를 사용하는 것입니다. 그러나이 문제를 해결할 다른 방법이 있는지, 그리고 있다면 거기에 가장 적은 오버 헤드가 발생하는지 궁금합니다. 속도가 우선입니다.
스크린 캐스팅 프로그램은 게임 푸티지를 녹화하기위한 것이지만 옵션이 좁아지면이 범위를 벗어나는 다른 제안이 여전히 열려 있습니다. 결국 지식은 나쁘지 않습니다.
편집 : 나는이 기사 를 보았습니다 : 화면을 캡처하는 다양한 방법 . Windows Media API 방식과 DirectX 방식을 소개했습니다. 결론에서 하드웨어 가속을 비활성화하면 캡처 응용 프로그램의 성능을 크게 향상시킬 수 있습니다. 왜 이런지 궁금합니다. 누구든지 나를 위해 누락 된 공백을 채울 수 있습니까?
편집 : Camtasia와 같은 스크린 캐스팅 프로그램은 자체 캡처 드라이버를 사용한다는 것을 읽었습니다. 누군가 어떻게 작동하는지, 왜 더 빠른지에 대해 깊이 설명해 줄 수 있습니까? 그런 식으로 구현하는 데 지침이 필요할 수도 있지만 어쨌든 기존 문서가 있다고 확신합니다.
또한 이제 FRAPS가 화면을 기록하는 방법을 알고 있습니다. 기본 그래픽 API를 후크하여 백 버퍼에서 읽습니다. 내가 이해 한 바에 따르면 비디오 RAM이 아닌 시스템 RAM에서 읽는 것이기 때문에 프론트 버퍼에서 읽는 것보다 빠릅니다. 여기서 기사를 읽을 수 있습니다 .
답변
이것이 단일 프레임을 수집하는 데 사용하는 것이지만, 이것을 수정하고 두 대상을 항상 열어두면 파일 이름에 대한 정적 카운터를 사용하여 디스크에 “스트리밍”할 수 있습니다. -어디서 찾았는지 기억이 나지 않지만 누구에게나 수정되었습니다!
void dump_buffer()
{
IDirect3DSurface9* pRenderTarget=NULL;
IDirect3DSurface9* pDestTarget=NULL;
const char file[] = "Pickture.bmp";
// sanity checks.
if (Device == NULL)
return;
// get the render target surface.
HRESULT hr = Device->GetRenderTarget(0, &pRenderTarget);
// get the current adapter display mode.
//hr = pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode);
// create a destination surface.
hr = Device->CreateOffscreenPlainSurface(DisplayMde.Width,
DisplayMde.Height,
DisplayMde.Format,
D3DPOOL_SYSTEMMEM,
&pDestTarget,
NULL);
//copy the render target to the destination surface.
hr = Device->GetRenderTargetData(pRenderTarget, pDestTarget);
//save its contents to a bitmap file.
hr = D3DXSaveSurfaceToFile(file,
D3DXIFF_BMP,
pDestTarget,
NULL,
NULL);
// clean up.
pRenderTarget->Release();
pDestTarget->Release();
}
답변
편집 : 이것이 첫 번째 편집 링크 아래에 “GDI 방식”으로 표시되어 있음을 알 수 있습니다. 이것은 여전히 해당 사이트의 성능 조언을 사용하는 적절한 방법이므로 30fps에 쉽게 도달 할 수 있습니다.
에서 이 주석 (난, 난 그냥 않는 사람을 참조하고있어 이런 일을 경험이 없음) :
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);
// ..delete the bitmap you were using to capture frames..
DeleteObject(hbDesktop);
// ..and delete the context you created
DeleteDC(hDest);
나는 이것이 가장 빠르다고 말하지는 않지만 BitBlt
호환되는 장치 컨텍스트간에 복사하는 경우 일반적으로 작업이 매우 빠릅니다.
참고로, 열기 브로드 소프트웨어 자신의 일환으로이 같은 구현 뭔가 “dc_capture” 오히려 대상 컨텍스트를 만들지 않고 있지만, 방법, hDest
사용 CreateCompatibleDC
그들이을 사용하여 IDXGISurface1
다이렉트 X 10 +와 함께 작동합니다. 이에 대한 지원이없는 경우로 넘어갑니다 CreateCompatibleDC
.
특정 응용 프로그램을 사용하도록 변경하려면 첫 번째 줄을 게임 창의 핸들 GetDC(game)
위치 로 변경 game
한 다음 오른쪽 height
및width
.
hDest / hbDesktop에 픽셀이 있으면 여전히 파일로 저장해야하지만 화면 캡처를 수행하는 경우 특정 수의 픽셀을 메모리에 버퍼링하고 비디오 파일에 저장하려고한다고 생각합니다. 정적 이미지를 디스크에 저장하기위한 코드를 가리 키지 않습니다.
답변
DirectX 응용 프로그램 용 FRAPS와 유사한 비디오 캡처 소프트웨어를 작성했습니다. 소스 코드를 사용할 수 있으며이 기사에서는 일반적인 기술에 대해 설명합니다. 보다http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/를
실적과 관련된 질문에
-
DirectX는 프론트 버퍼에서 읽을 때를 제외하고 GDI보다 빠릅니다. 내 접근 방식은 FRAPS와 비슷합니다 (backbuffer에서 읽음). Direct3D 인터페이스에서 일련의 메소드를 가로 챕니다.
-
응용 프로그램에 미치는 영향을 최소화하면서 실시간으로 비디오를 녹화하려면 빠른 코덱이 필요합니다. FRAPS는 자체 무손실 비디오 코덱을 사용합니다. Lagarith와 HUFFYUV는 실시간 애플리케이션을 위해 설계된 일반적인 무손실 비디오 코덱입니다. 비디오 파일을 출력하려면 해당 파일을 살펴보십시오.
-
스크린 캐스트를 기록하는 또 다른 방법은 미러 드라이버를 작성하는 것입니다. Wikipedia에 따르면 : 비디오 미러링이 활성화되면 시스템이 미러링 된 영역 내부의 위치에서 기본 비디오 장치로 끌 때마다 미러링 된 비디오 장치에서 그리기 작업의 사본이 실시간으로 실행됩니다. MSDN의 미러 드라이버 ( http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx)를 참조 하십시오 .
답변
d3d9를 사용하여 백 버퍼를 가져 와서 d3dx 라이브러리를 사용하여 png 파일로 저장합니다.
IDirect3DSurface9 * surface; // GetBackBuffer idirect3ddevice9-> GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, & surface); // 표면을 저장 D3DXSaveSurfaceToFileA ( "filename.png", D3DXIFF_PNG, surface, NULL, NULL); SAFE_RELEASE (표면);
이렇게하려면 다음과 같이 swapbuffer를 만들어야합니다.
d3dpps.SwapEffect = D3DSWAPEFFECT_COPY ; // for screenshots.
(스크린 샷을 찍기 전에 백 버퍼가 엉망이되지 않도록 보장합니다).
답변
필자의 인상에서 GDI 접근 방식과 DX 접근 방식은 본질적으로 다릅니다. GDI를 사용하여 페인팅하면 FLUSH 방법이 적용되고 FLUSH 방식은 프레임을 그린 다음 지우고 동일한 버퍼에서 다른 프레임을 다시 그립니다. 이로 인해 게임에서 깜박임으로 높은 프레임 속도가 필요합니다.
- DX가 더 빠른 이유는 무엇입니까? DX (또는 그래픽 세계)에서는 이중 버퍼 렌더링이라는보다 성숙한 방법이 적용됩니다. 두 개의 버퍼가 존재하는 경우 전면 버퍼를 하드웨어에 제공 할 때 다른 버퍼로 렌더링 한 다음 프레임 1이 끝난 후 렌더링이 완료되면 시스템은 다른 버퍼로 스왑 (하드웨어에 표시하기 위해 잠금 및 이전 버퍼 릴리스)하여 렌더링 비 효율성이 크게 향상됩니다.
- 하드웨어 가속을 더 빨리 끄는 이유는 무엇입니까? 이중 버퍼 렌더링을 사용하면 FPS가 향상되지만 렌더링 시간은 여전히 제한적입니다. 최신 그래픽 하드웨어는 일반적으로 앤티 앨리어싱과 같이 일반적으로 렌더링하는 동안 많은 최적화가 필요합니다. 고품질 그래픽이 필요하지 않은 경우이 옵션을 비활성화 할 수 있습니다. 그러면 시간이 절약됩니다.
정말로 필요한 것은 사람들이 논의한 것에 완전히 동의하는 재생 시스템이라고 생각합니다.
답변
화면 캡처를위한 GDI 방법을 구현 한 클래스를 작성했습니다. GetFrontBuffer를 통해 DirectX 메서드를 찾은 후 더 빠른 속도를 기대하면서 추가 속도를 원했습니다.
GDI 성능이 약 2.5 배 더 빠르다는 사실에 놀랐습니다. 듀얼 모니터 디스플레이를 100 번 시험 한 후 GDI 구현은 화면 캡처 당 평균 0.65 초, DirectX 방법은 평균 1.72 초였습니다. 내 테스트에 따르면 GDI는 GetFrontBuffer보다 확실히 빠릅니다.
GetRenderTargetData를 통해 Brandrew의 코드가 DirectX를 테스트하도록 작동하지 못했습니다. 화면 사본이 순전히 검은 색으로 나왔습니다. 그러나 빈 화면을 매우 빠르게 복사 할 수 있습니다! 나는 그것을 계속 고민하고 실제 결과를 볼 수있는 작동 버전을 얻을 수 있기를 바랍니다.
답변
내가 얻을 수 있었던 몇 가지 : OSS 드라이버를 모르지만 분명히 “미러 드라이버”를 사용하는 것이 빠릅니다.
RDP가 다른 원격 제어 소프트웨어에 비해 왜 빠릅니까?
또한 StretchRect의 일부 회선을 사용하는 것이 BitBlt보다 빠릅니다.
http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193
그리고 당신이 언급 한 것 (D3D dll에 연결된 후크)은 아마도 D3D 응용 프로그램의 유일한 방법이지만 Windows XP 데스크톱 캡처에서는 작동하지 않을 것입니다. 이제 일반 데스크톱 창에서 속도가 비슷한 플랩이 있었으면 좋겠습니다.
에어로에서는 플랩 같은 고리를 사용할 수 있지만 XP 사용자는 운이 좋지 않을 것이라고 생각합니다.
또한 화면 비트 깊이를 변경하거나 하드웨어 가속을 비활성화합니다. 도움이 될 수 있습니다 (및 / 또는 에어로 비활성화).
https://github.com/rdp/screen-capture-recorder-program 에는 합리적으로 빠른 BitBlt 기반 캡처 유틸리티와 설치의 일부로 벤치마킹 기가 포함되어있어 BitBlt 속도를 벤치마킹하여 최적화 할 수 있습니다.
또한 VirtualDub에는 “opengl”화면 캡처 모듈이있어 속도가 빠르고 변경 감지와 같은 작업을 수행합니다. http://www.virtualdub.org/blog/pivot/entry.php?id=290