From aafe88ac8ba1436bc42cbf65af2d22e8d7955e21 Mon Sep 17 00:00:00 2001 From: "DESKTOP-4RNDQIC\\29019" <290198252@qq.com> Date: Tue, 5 Oct 2021 10:27:53 +0800 Subject: [PATCH] no message --- client/qt_gl_/yuvgl/main.cpp | 238 ++++++++++++++++++- client/qt_gl_/yuvgl/media/DXGICapture.cpp | 7 +- client/qt_gl_/yuvgl/media/screen_capture.cpp | 122 ++++++++++ client/qt_gl_/yuvgl/media/screen_capture.h | 2 + client/qt_gl_/yuvgl/yuvgl.pro | 2 +- client/qt_gl_/yuvgl/yuvgl.pro.user | 2 +- 6 files changed, 366 insertions(+), 7 deletions(-) diff --git a/client/qt_gl_/yuvgl/main.cpp b/client/qt_gl_/yuvgl/main.cpp index 7dca234..9a81bfe 100644 --- a/client/qt_gl_/yuvgl/main.cpp +++ b/client/qt_gl_/yuvgl/main.cpp @@ -8,6 +8,16 @@ #include #include #include "media/screen_capture.h" +#include "media/DXGICapture.h" +#include +#include +#include +#include +#include + +#if _MSC_VER >= 1600 +#pragma execution_character_set("utf-8") +#endif #ifdef __MINGW32__ #include @@ -18,15 +28,239 @@ int RegiesterOwnType(){ return 0; } +IDirect3DDevice9* g_pd3dDevice = nullptr; + +// 全???====================================================== + +// 建立D3DDevice + +LPDIRECT3D9 g_pD3D = nullptr; // Used to create the D3DDevice + +// (我?的?)render?置,用??生最後影像的?置 + + +// ============================================================= +HRESULT ScreenGrab(LPDIRECT3DDEVICE9 pDev) + +{ + HRESULT hr; + D3DDISPLAYMODE mode; + if (FAILED(hr=pDev->GetDisplayMode(0, &mode))) //第一???是Swap Chain,跟?重???有防止破碎 + return hr; + + IDirect3DSurface9* pSurface; + + if (FAILED(hr=pDev->CreateOffscreenPlainSurface(mode.Width,mode.Height, + D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL))) + return hr; + + + if (FAILED(hr=pDev->GetFrontBufferData(0,pSurface))) { + pSurface->Release(); + return hr; + } + D3DLOCKED_RECT lockedRect; + if(FAILED(pSurface->LockRect(&lockedRect,NULL,D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) + { + printf("Unable to Lock Front Buffer Surface"); + return 1; + } + BYTE* pBits = new BYTE[2960*1440*3]; + for(int i=0;iUnlockRect(); + + SetCursor(LoadCursor(NULL,IDC_ARROW)); + + // release the image surface + + // ?放影像表面 + + pSurface->Release(); + + + + // return status of save operation to caller + + // 回?Handler + + return hr; + +} + + + +QVector GetMonitors() +{ + QVector ret; + HRESULT hr = S_OK; + CDXGICapture dxgiCapture; + hr = dxgiCapture.Initialize(); + if (FAILED(hr)) { + printf("Error[0x%08X]: CDXGICapture::Initialize failed.\n", hr); + return ret; + } + + int nMonitorCount = dxgiCapture.GetDublicatorMonitorInfoCount(); + printf("{\n"); + if (nMonitorCount > 0) { + printf(" \"count\" : %u,\n", nMonitorCount); + printf(" \"monitors\" : [\n"); + for (int i = 0; i < nMonitorCount; ++i) { + const tagDublicatorMonitorInfo *pInfo = dxgiCapture.GetDublicatorMonitorInfo(i); + if (nullptr != pInfo) { + printf(" {\n"); + printf(" \"idx\" : %u,\n", pInfo->Idx); + printf(" \"name\" : \"%S\",\n", pInfo->DisplayName); + printf(" \"x\" : %d,\n", pInfo->Bounds.X); + printf(" \"y\" : %d,\n", pInfo->Bounds.Y); + printf(" \"width\" : %d,\n", pInfo->Bounds.Width); + printf(" \"height\" : %d,\n", pInfo->Bounds.Height); + printf(" \"rotation\" : %d\n", pInfo->RotationDegrees); + if (i < (nMonitorCount - 1)) { + printf(" },\n"); + } + else { + printf(" }\n"); + } + ret.push_back(*pInfo); + } + } + printf(" ]\n"); + } + else { + printf(" \"count\" : %u\n", nMonitorCount); + } + printf("}\n"); + + dxgiCapture.Terminate(); + + return ret; +} + +HRESULT InitD3D( HWND hWnd ) + +{ + + // Create the D3D object, which is needed to create the D3DDevice. + + // D3DDevice所需要的D3D物件,Direct3DCreate9回?D3DDevice,?入值?使用者安?DirectX的版本 + + if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) + + return E_FAIL; + + + + // Set up the structure used to create the D3DDevice. Most parameters are + + // zeroed out. We set Windowed to TRUE, since we want to do D3D in a + + // window, and then set the SwapEffect to "discard", which is the most + + // efficient method of presenting the back buffer to the display. And + + // we request a back buffer format that matches the current desktop display + + // format. + + /* + + 用?建立D3DDevice的??。大多????0。 + + ?定是否?"?窗化"?真,就是?示??窗化。 + + 如果?D3D於?窗?行,?SwapEffect定"discard",??在後端??呈???最有效率。 + + ?且我?要求後端??的?示格式??在的?面相符。 + + */ + + D3DPRESENT_PARAMETERS d3dpp; + + ZeroMemory( &d3dpp, sizeof( d3dpp ) ); //初始化d3d的?? + + d3dpp.Windowed = TRUE; //?定?窗化 + + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //提高效率 + + d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; //??有呈??面相符格式(竟然是?定未知= =) + + + + // Create the Direct3D device. Here we are using the default adapter (most + + // systems only have one, unless they have multiple graphics hardware cards + + // installed) and requesting the HAL (which is saying we want the hardware + + // device rather than a software one). Software vertex processing is + + // specified since we know it will work on all cards. On cards that support + + // hardware vertex processing, though, we would see a big performance gain + + // by specifying hardware vertex processing. + + /* + + 建立Direct3D?置。我?使用??的adapter(?似?置的意思= =)。 + + ?大多?的使用者??只有一??置(?示卡),除非他?有其多的?示卡。 + + ?且要求HAL,也就是?先用?示卡?示,而不是用???理。 + + 既然我?知道????(角)?理的?理方式被定?所有?示卡。 + + 於支援硬????理的?示卡上,我??看到?佳的?行效率。 + + */ + + if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, //??adapter + + D3DDEVTYPE_HAL, //硬?加速 + + hWnd, //Handler名? + + //D3DCREATE_SOFTWARE_VERTEXPROCESSING, //最後竟然用??? + + D3DCREATE_HARDWARE_VERTEXPROCESSING, //改用硬?加速吧 + + &d3dpp, //D3D?? + + &g_pd3dDevice //D3D最後?示?置?? + + ) ) ) + + { + + return E_FAIL; + + } + + + // Device state would normally be set here + + return S_OK; + +} + int main(int argc, char *argv[]) { - ScreenCapture g; - g.EnumScreen(); + setbuf(stdout, NULL);//让printf立即输出 + QssEventFilter filter; QApplication app(argc, argv); + MainWindow main; + InitD3D((HWND)main.winId()); + ScreenGrab( g_pd3dDevice); main.setWindowTitle("流媒体测试工具"); main.setFixedSize(1920,1080); main.show(); diff --git a/client/qt_gl_/yuvgl/media/DXGICapture.cpp b/client/qt_gl_/yuvgl/media/DXGICapture.cpp index bce0f99..09156a0 100644 --- a/client/qt_gl_/yuvgl/media/DXGICapture.cpp +++ b/client/qt_gl_/yuvgl/media/DXGICapture.cpp @@ -657,7 +657,8 @@ HRESULT CDXGICapture::CaptureToFile(_In_ LPCWSTR lpcwOutputFileName, _Out_opt_ B m_ipD2D1RenderTarget->BeginDraw(); // clear background color m_ipD2D1RenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black, 1.0f)); - m_ipD2D1RenderTarget->DrawBitmap(ipD2D1SourceBitmap, rcTarget, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rcSource); + m_ipD2D1RenderTarget->DrawBitmap(ipD2D1SourceBitmap, rcTarget, 1.0f, + D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rcSource); // Reset transform //m_ipD2D1RenderTarget->SetTransform(D2D1::Matrix3x2F::Identity()); // Logo draw sample @@ -671,8 +672,8 @@ HRESULT CDXGICapture::CaptureToFile(_In_ LPCWSTR lpcwOutputFileName, _Out_opt_ B if (nullptr != pRetRenderDuration) { *pRetRenderDuration = (UINT)((std::chrono::system_clock::now() - startTick).count() / 10000); } - - hr = DXGICaptureHelper::SaveImageToFile(m_ipWICImageFactory, m_ipWICOutputBitmap, lpcwOutputFileName); + hr = DXGICaptureHelper::SaveImageToFile(m_ipWICImageFactory, + m_ipWICOutputBitmap, lpcwOutputFileName); if (FAILED(hr)) { return hr; } diff --git a/client/qt_gl_/yuvgl/media/screen_capture.cpp b/client/qt_gl_/yuvgl/media/screen_capture.cpp index 370a964..41b21a5 100644 --- a/client/qt_gl_/yuvgl/media/screen_capture.cpp +++ b/client/qt_gl_/yuvgl/media/screen_capture.cpp @@ -5,6 +5,128 @@ #include #include +#define WIDEN2(x) L ## x + #define WIDEN(x) WIDEN2(x) + #define __WFILE__ WIDEN(__FILE__) + #define HRCHECK(__expr) {hr=(__expr);if(FAILED(hr)){wprintf(L"FAILURE 0x%08X (%i)\n\tline: %u file: '%s'\n\texpr: '" WIDEN(#__expr) L"'\n",hr, hr, __LINE__,__WFILE__);goto cleanup;}} + #define RELEASE(__p) {if(__p!=nullptr){__p->Release();__p=nullptr;}} + +// 缺enum方法 +// https://www.gamedev.net/forums/topic/132636-enum-displaymode--dx9--false/ + +HRESULT SavePixelsToFile32bppPBGRA(UINT width, UINT height, UINT stride, LPBYTE pixels, LPWSTR filePath, const GUID &format) + { + if (!filePath || !pixels) + return E_INVALIDARG; + + HRESULT hr = S_OK; + IWICImagingFactory *factory = nullptr; + IWICBitmapEncoder *encoder = nullptr; + IWICBitmapFrameEncode *frame = nullptr; + IWICStream *stream = nullptr; + GUID pf = GUID_WICPixelFormat32bppPBGRA; + BOOL coInit = CoInitialize(nullptr); + + HRCHECK(CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory))); + HRCHECK(factory->CreateStream(&stream)); + HRCHECK(stream->InitializeFromFilename(filePath, GENERIC_WRITE)); + HRCHECK(factory->CreateEncoder(format, nullptr, &encoder)); + HRCHECK(encoder->Initialize(stream, WICBitmapEncoderNoCache)); + HRCHECK(encoder->CreateNewFrame(&frame, nullptr)); // we don't use options here + HRCHECK(frame->Initialize(nullptr)); // we dont' use any options here + HRCHECK(frame->SetSize(width, height)); + HRCHECK(frame->SetPixelFormat(&pf)); + HRCHECK(frame->WritePixels(height, stride, stride * height, pixels)); + HRCHECK(frame->Commit()); + HRCHECK(encoder->Commit()); + + cleanup: + RELEASE(stream); + RELEASE(frame); + RELEASE(encoder); + RELEASE(factory); + if (coInit) CoUninitialize(); + return hr; + } + +HRESULT Direct3D9TakeScreenshots(UINT adapter, UINT count) +{ + HRESULT hr = S_OK; + IDirect3D9 *d3d = nullptr; + IDirect3DDevice9 *device = nullptr; + IDirect3DSurface9 *surface = nullptr; + D3DPRESENT_PARAMETERS parameters = { 0 }; + D3DDISPLAYMODE mode; + D3DLOCKED_RECT rc; + UINT pitch; + SYSTEMTIME st; + LPBYTE *shots = nullptr; + + // init D3D and get screen size + d3d = Direct3DCreate9(D3D_SDK_VERSION); + HRCHECK(d3d->GetAdapterDisplayMode(adapter, &mode)); + + parameters.Windowed = TRUE; + parameters.BackBufferCount = 1; + parameters.BackBufferHeight = mode.Height; + parameters.BackBufferWidth = mode.Width; + parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + parameters.hDeviceWindow = NULL; + + // create device & capture surface + HRCHECK(d3d->CreateDevice(adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶meters, &device)); + HRCHECK(device->CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, nullptr)); + + // compute the required buffer size + HRCHECK(surface->LockRect(&rc, NULL, 0)); + pitch = rc.Pitch; + HRCHECK(surface->UnlockRect()); + + // allocate screenshots buffers + shots = new LPBYTE[count]; + for (UINT i = 0; i < count; i++) + { + shots[i] = new BYTE[pitch * mode.Height]; + } + + GetSystemTime(&st); // measure the time we spend doing captures + wprintf(L"%i:%i:%i.%i\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); + for (UINT i = 0; i < count; i++) + { + // get the data + HRCHECK(device->GetFrontBufferData(0, surface)); + + // copy it into our buffers + HRCHECK(surface->LockRect(&rc, NULL, 0)); + CopyMemory(shots[i], rc.pBits, rc.Pitch * mode.Height); + HRCHECK(surface->UnlockRect()); + } + GetSystemTime(&st); + wprintf(L"%i:%i:%i.%i\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); + + // save all screenshots + for (UINT i = 0; i < count; i++) + { + WCHAR file[100]; + wsprintf(file, L"cap%i.png", i); + HRCHECK(SavePixelsToFile32bppPBGRA(mode.Width, mode.Height, pitch, shots[i], file, GUID_ContainerFormatPng)); + } + +cleanup: + if (shots != nullptr) + { + for (UINT i = 0; i < count; i++) + { + delete shots[i]; + } + delete[] shots; + } + RELEASE(surface); + RELEASE(device); + RELEASE(d3d); + return hr; +} + ScreenCapture::ScreenCapture() { diff --git a/client/qt_gl_/yuvgl/media/screen_capture.h b/client/qt_gl_/yuvgl/media/screen_capture.h index 4815863..3226920 100644 --- a/client/qt_gl_/yuvgl/media/screen_capture.h +++ b/client/qt_gl_/yuvgl/media/screen_capture.h @@ -2,6 +2,8 @@ #define SCREEN_CAPTURE #include +#include // we use WIC for saving images +#include // DirectX 9 header class ScreenCapture { diff --git a/client/qt_gl_/yuvgl/yuvgl.pro b/client/qt_gl_/yuvgl/yuvgl.pro index 309db6f..5eb4d92 100644 --- a/client/qt_gl_/yuvgl/yuvgl.pro +++ b/client/qt_gl_/yuvgl/yuvgl.pro @@ -99,7 +99,7 @@ contains(DEFINES, __MINGW32__){ libavformat.a libavutil.a \ libswresample.a libswscale.a fdk-aac.lib ws2_32.lib libeay32.lib ssleay32.lib \ shell32.lib gdi32.lib crypt32.lib User32.lib GDI32.lib Advapi32.lib zlibstaticd.lib Secur32.lib \ - Bcrypt.lib Kernel32.lib portaudio_x86.lib ole32.lib oleaut32.lib strmiids.lib libx264.lib + Bcrypt.lib Kernel32.lib portaudio_x86.lib ole32.lib oleaut32.lib strmiids.lib libx264.lib d3d9.lib } else{ diff --git a/client/qt_gl_/yuvgl/yuvgl.pro.user b/client/qt_gl_/yuvgl/yuvgl.pro.user index fdd07f0..2a58f87 100644 --- a/client/qt_gl_/yuvgl/yuvgl.pro.user +++ b/client/qt_gl_/yuvgl/yuvgl.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId