2025-03-13 23:34:33 +08:00
# pragma once
# include "stdafx.h"
# include "ScreenCapture.h"
# include "common/commands.h"
// ֻҪ<D6BB> 㰲װ<E3B0B2> <D7B0> Windows 8 SDK <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ߰汾<DFB0> <E6B1BE> Windows SDK<44> <4B> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ҵ<EFBFBD> dxgi1_2.h <20> <> <EFBFBD> ɹ<EFBFBD> <C9B9> <EFBFBD> <EFBFBD> 롣
// <20> <> <EFBFBD> <EFBFBD> Windows 8 <20> <> <EFBFBD> <EFBFBD> <EFBFBD> °汾<C2B0> <E6B1BE> <EFBFBD> <EFBFBD> ֧<EFBFBD> <D6A7>
# include <dxgi1_2.h>
# include <d3d11.h>
# pragma comment(lib, "d3d11.lib")
2025-08-02 23:41:02 +08:00
# pragma comment(lib, "dxgi.lib")
2025-03-13 23:34:33 +08:00
// author: ChatGPT
// update: 962914132@qq.com
// DXGI 1.2<EFBFBD> <EFBFBD> IDXGIOutputDuplication<EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ȴ<EFBFBD> ͳ GDI <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ͨ<EFBFBD> <CDA8> <EFBFBD> <EFBFBD> 3 <20> <> <EFBFBD> <EFBFBD> 10 <20> <> ֮<EFBFBD> 䣬<EFBFBD> <E4A3AC> <EFBFBD> <EFBFBD> ȡ<EFBFBD> <C8A1> <EFBFBD> <EFBFBD> Ӳ<EFBFBD> <D3B2> <EFBFBD> <EFBFBD> <EFBFBD> ֱ<EFBFBD> <D6B1> ʺ<EFBFBD> ʹ <EFBFBD> ó<EFBFBD> <C3B3> <EFBFBD> <EFBFBD> <EFBFBD>
class ScreenCapturerDXGI : public ScreenCapture {
private :
ID3D11Device * d3dDevice = nullptr ;
ID3D11DeviceContext * d3dContext = nullptr ;
IDXGIOutputDuplication * deskDupl = nullptr ;
ID3D11Texture2D * cpuTexture = nullptr ;
BYTE * m_NextBuffer = nullptr ;
public :
2025-07-16 04:26:01 +08:00
ScreenCapturerDXGI ( BYTE algo , int gop = DEFAULT_GOP , BOOL all = FALSE ) : ScreenCapture ( 32 , algo , all ) {
2025-03-13 23:34:33 +08:00
m_GOP = gop ;
2025-08-02 23:41:02 +08:00
InitDXGI ( all ) ;
2025-03-13 23:34:33 +08:00
Mprintf ( " Capture screen with DXGI: GOP= %d \n " , m_GOP ) ;
}
~ ScreenCapturerDXGI ( ) {
CleanupDXGI ( ) ;
SAFE_DELETE_ARRAY ( m_FirstBuffer ) ;
SAFE_DELETE_ARRAY ( m_NextBuffer ) ;
SAFE_DELETE_ARRAY ( m_RectBuffer ) ;
}
2025-08-02 23:41:02 +08:00
void InitDXGI ( BOOL all ) {
m_iScreenX = 0 ;
m_iScreenY = 0 ;
2025-03-13 23:34:33 +08:00
// 1. <20> <> <EFBFBD> <EFBFBD> D3D11 <20> 豸
D3D11CreateDevice ( nullptr , D3D_DRIVER_TYPE_HARDWARE , NULL , 0 , nullptr , 0 , D3D11_SDK_VERSION , & d3dDevice , nullptr , & d3dContext ) ;
2025-08-02 23:41:02 +08:00
IDXGIFactory1 * pFactory = nullptr ;
IDXGIAdapter1 * dxgiAdapter = nullptr ;
2025-03-13 23:34:33 +08:00
IDXGIOutput * dxgiOutput = nullptr ;
IDXGIOutput1 * dxgiOutput1 = nullptr ;
2025-04-07 14:21:42 +08:00
2025-08-02 23:41:02 +08:00
// 2. <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
CreateDXGIFactory1 ( __uuidof ( IDXGIFactory1 ) , ( void * * ) & pFactory ) ;
if ( ! pFactory ) return ;
2025-04-07 14:21:42 +08:00
2025-08-02 23:41:02 +08:00
do {
// 3. <20> <> ȡ<EFBFBD> 豸
static UINT idx = 0 ;
idx = pFactory - > EnumAdapters1 ( idx , & dxgiAdapter ) = = DXGI_ERROR_NOT_FOUND ? 0 : idx ;
if ( ! dxgiAdapter ) pFactory - > EnumAdapters1 ( idx , & dxgiAdapter ) ;
2025-04-07 14:21:42 +08:00
if ( ! dxgiAdapter ) break ;
// 4. <20> <> ȡ DXGI <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ļ<EFBFBD> <C4BB>
2025-08-02 23:41:02 +08:00
static UINT screen = 0 ;
HRESULT r = dxgiAdapter - > EnumOutputs ( screen + + , & dxgiOutput ) ;
if ( r = = DXGI_ERROR_NOT_FOUND & & all ) {
screen = 0 ;
idx + + ;
dxgiAdapter - > Release ( ) ;
dxgiAdapter = nullptr ;
continue ;
}
2025-04-07 14:21:42 +08:00
if ( ! dxgiOutput ) break ;
// 5. <20> <> ȡ DXGI <20> <> <EFBFBD> <EFBFBD> 1
dxgiOutput - > QueryInterface ( __uuidof ( IDXGIOutput1 ) , ( void * * ) & dxgiOutput1 ) ;
if ( ! dxgiOutput1 ) break ;
// 6. <20> <> <EFBFBD> <EFBFBD> Desktop Duplication
dxgiOutput1 - > DuplicateOutput ( d3dDevice , & deskDupl ) ;
if ( ! deskDupl ) break ;
// 7. <20> <> ȡ<EFBFBD> <C8A1> Ļ<EFBFBD> <C4BB> С
DXGI_OUTDUPL_DESC duplDesc ;
deskDupl - > GetDesc ( & duplDesc ) ;
m_ulFullWidth = duplDesc . ModeDesc . Width ;
m_ulFullHeight = duplDesc . ModeDesc . Height ;
// 8. <20> <> <EFBFBD> <EFBFBD> CPU <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
D3D11_TEXTURE2D_DESC desc = { } ;
desc . Width = m_ulFullWidth ;
desc . Height = m_ulFullHeight ;
desc . MipLevels = 1 ;
desc . ArraySize = 1 ;
desc . Format = DXGI_FORMAT_B8G8R8A8_UNORM ;
desc . SampleDesc . Count = 1 ;
desc . Usage = D3D11_USAGE_STAGING ;
desc . CPUAccessFlags = D3D11_CPU_ACCESS_READ ;
d3dDevice - > CreateTexture2D ( & desc , NULL , & cpuTexture ) ;
// 9. <20> <> ʼ <EFBFBD> <CABC> BITMAPINFO
m_BitmapInfor_Full = ( BITMAPINFO * ) new char [ sizeof ( BITMAPINFO ) ] ;
memset ( m_BitmapInfor_Full , 0 , sizeof ( BITMAPINFO ) ) ;
m_BitmapInfor_Full - > bmiHeader . biSize = sizeof ( BITMAPINFOHEADER ) ;
m_BitmapInfor_Full - > bmiHeader . biWidth = m_ulFullWidth ;
m_BitmapInfor_Full - > bmiHeader . biHeight = m_ulFullHeight ;
m_BitmapInfor_Full - > bmiHeader . biPlanes = 1 ;
m_BitmapInfor_Full - > bmiHeader . biBitCount = 32 ;
m_BitmapInfor_Full - > bmiHeader . biCompression = BI_RGB ;
m_BitmapInfor_Full - > bmiHeader . biSizeImage = m_ulFullWidth * m_ulFullHeight * 4 ;
// 10. <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ļ<EFBFBD> <C4BB> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
m_FirstBuffer = new BYTE [ m_BitmapInfor_Full - > bmiHeader . biSizeImage + 1 ] ;
m_NextBuffer = new BYTE [ m_BitmapInfor_Full - > bmiHeader . biSizeImage + 1 ] ;
m_RectBuffer = new BYTE [ m_BitmapInfor_Full - > bmiHeader . biSizeImage * 2 + 12 ] ;
2025-08-02 23:41:02 +08:00
break ;
} while ( true ) ;
2025-03-13 23:34:33 +08:00
// <20> ͷ<EFBFBD> DXGI <20> <> Դ
2025-04-07 14:21:42 +08:00
if ( dxgiOutput1 ) dxgiOutput1 - > Release ( ) ;
if ( dxgiOutput ) dxgiOutput - > Release ( ) ;
if ( dxgiAdapter ) dxgiAdapter - > Release ( ) ;
2025-08-02 23:41:02 +08:00
if ( pFactory ) pFactory - > Release ( ) ;
2025-04-07 14:21:42 +08:00
}
bool IsInitSucceed ( ) const {
return cpuTexture ;
2025-03-13 23:34:33 +08:00
}
void CleanupDXGI ( ) {
if ( cpuTexture ) cpuTexture - > Release ( ) ;
if ( deskDupl ) deskDupl - > Release ( ) ;
if ( d3dContext ) d3dContext - > Release ( ) ;
if ( d3dDevice ) d3dDevice - > Release ( ) ;
}
LPBYTE GetFirstScreenData ( ULONG * ulFirstScreenLength ) override {
int ret = CaptureFrame ( m_FirstBuffer , ulFirstScreenLength , 1 ) ;
if ( ret )
return nullptr ;
2025-03-30 18:03:01 +08:00
if ( m_bAlgorithm = = ALGORITHM_GRAY ) {
ToGray ( 1 + m_RectBuffer , 1 + m_RectBuffer , m_BitmapInfor_Full - > bmiHeader . biSizeImage ) ;
}
2025-03-13 23:34:33 +08:00
m_FirstBuffer [ 0 ] = TOKEN_FIRSTSCREEN ;
return m_FirstBuffer ;
}
LPBYTE ScanNextScreen ( ) override {
ULONG ulNextScreenLength = 0 ;
int ret = CaptureFrame ( m_NextBuffer , & ulNextScreenLength , 0 ) ;
if ( ret )
return nullptr ;
return m_NextBuffer ;
}
virtual LPBYTE GetFirstBuffer ( ) const {
return m_FirstBuffer + 1 ;
}
private :
int CaptureFrame ( LPBYTE buffer , ULONG * frameSize , int reservedBytes ) {
// 1. <20> <> ȡ<EFBFBD> <C8A1> һ ֡
IDXGIResource * desktopResource = nullptr ;
DXGI_OUTDUPL_FRAME_INFO frameInfo ;
HRESULT hr = deskDupl - > AcquireNextFrame ( 100 , & frameInfo , & desktopResource ) ;
if ( FAILED ( hr ) ) {
return - 1 ;
}
// 2. <20> <> ȡ ID3D11Texture2D
ID3D11Texture2D * texture = nullptr ;
hr = desktopResource - > QueryInterface ( __uuidof ( ID3D11Texture2D ) , ( void * * ) & texture ) ;
if ( FAILED ( hr ) ) {
deskDupl - > ReleaseFrame ( ) ;
return - 2 ;
}
// 3. <20> <> <EFBFBD> Ƶ<EFBFBD> CPU <20> <> <EFBFBD> <EFBFBD>
d3dContext - > CopyResource ( cpuTexture , texture ) ;
// 4. <20> ͷ<EFBFBD> DXGI <20> <> Դ
deskDupl - > ReleaseFrame ( ) ;
texture - > Release ( ) ;
desktopResource - > Release ( ) ;
// 5. <20> <> ȡ<EFBFBD> <C8A1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
D3D11_MAPPED_SUBRESOURCE mapped ;
hr = d3dContext - > Map ( cpuTexture , 0 , D3D11_MAP_READ , 0 , & mapped ) ;
if ( FAILED ( hr ) ) {
return - 3 ;
}
// 6. <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ݵ<EFBFBD> <DDB5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ֱ<EFBFBD> <D6B1> ת<EFBFBD> <D7AA>
BYTE * pData = ( BYTE * ) mapped . pData ;
int rowSize = m_ulFullWidth * 4 ; // ÿ<> е <EFBFBD> <D0B5> ֽ<EFBFBD> <D6BD> <EFBFBD> <EFBFBD> <EFBFBD> RGBA<42> <41>
for ( int y = 0 ; y < m_ulFullHeight ; y + + ) {
// <20> <> <EFBFBD> <EFBFBD> Ŀ<EFBFBD> 껺<EFBFBD> <EABBBA> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ<EFBFBD> ã<EFBFBD> <C3A3> ӵײ<D3B5> <D7B2> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
int destIndex = reservedBytes + ( m_ulFullHeight - 1 - y ) * rowSize ;
int srcIndex = y * mapped . RowPitch ; // Direct3D <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ƫ<EFBFBD> <C6AB>
memcpy ( buffer + destIndex , pData + srcIndex , rowSize ) ;
}
// 7. <20> <> <EFBFBD> <EFBFBD>
d3dContext - > Unmap ( cpuTexture , 0 ) ;
* frameSize = m_ulFullWidth * m_ulFullHeight * 4 ;
return 0 ;
}
} ;