//#include "stdafx.h"
#include "DXGICaptor.h"
#include <Windows.h>
#include <stddef.h>
#include <stdio.h>
#include <QDebug>
#if _MSC_VER >= VS_VERSION
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "User32.lib")
#endif
#define RESET_OBJECT(obj) { if(obj) obj->Release(); obj = NULL; }
static BOOL g_bAttach = FALSE;
// DXGI_ERROR_DEVICE_REMOVED
// DXGI_ERROR_DEVICE_REMOVED
// DXGI_ERROR_DEVICE_RESET
VideoDXGICaptor::VideoDXGICaptor()
{
m_bInit = FALSE;
#if _MSC_VER >= VS_VERSION
m_hDevice = NULL;
m_hContext = NULL;
m_hDeskDupl = NULL;
ZeroMemory(&m_dxgiOutDesc, sizeof(m_dxgiOutDesc));
#endif
}
VideoDXGICaptor::~VideoDXGICaptor()
{
Deinit();
}
BOOL VideoDXGICaptor::Init()
{
HRESULT hr = S_OK;
#if _MSC_VER >= VS_VERSION
if (m_bInit)
{
return FALSE;
}
// Driver types supported
D3D_DRIVER_TYPE DriverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
// Feature levels supported
D3D_FEATURE_LEVEL FeatureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
D3D_FEATURE_LEVEL FeatureLevel;
//
// Create D3D device
//
for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
{
hr = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0,
FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION,
&m_hDevice, &FeatureLevel, &m_hContext);
if (SUCCEEDED(hr))
{
break;
}
}
if (FAILED(hr))
{
return FALSE;
}
//
// Get DXGI device
//
IDXGIDevice *hDxgiDevice = NULL;
hr = m_hDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&hDxgiDevice));
if (FAILED(hr))
{
return FALSE;
}
//
// Get DXGI adapter
//
IDXGIAdapter *hDxgiAdapter = NULL;
hr = hDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&hDxgiAdapter));
RESET_OBJECT(hDxgiDevice);
if (FAILED(hr))
{
return FALSE;
}
//
// Get output
//
INT nOutput = 0;
IDXGIOutput *hDxgiOutput = NULL;
hr = hDxgiAdapter->EnumOutputs(nOutput, &hDxgiOutput);
RESET_OBJECT(hDxgiAdapter);
if (FAILED(hr))
{
return FALSE;
}
//
// get output description struct
//
hDxgiOutput->GetDesc(&m_dxgiOutDesc);
m_iWidth = m_dxgiOutDesc.DesktopCoordinates.right - m_dxgiOutDesc.DesktopCoordinates.left;
m_iHeight = m_dxgiOutDesc.DesktopCoordinates.bottom - m_dxgiOutDesc.DesktopCoordinates.top;
qDebug()<<"m_iWidth"<<m_iWidth<<m_iHeight;
//
// QI for Output 1
//
IDXGIOutput1 *hDxgiOutput1 = NULL;
hr = hDxgiOutput->QueryInterface(__uuidof(hDxgiOutput1), reinterpret_cast<void**>(&hDxgiOutput1));
RESET_OBJECT(hDxgiOutput);
if (FAILED(hr))
{
return FALSE;
}
//
// Create desktop duplication
//
hr = hDxgiOutput1->DuplicateOutput(m_hDevice, &m_hDeskDupl);
RESET_OBJECT(hDxgiOutput1);
if (FAILED(hr))
{
return FALSE;
}
// 初始化成功
m_bInit = TRUE;
return TRUE;
#else
// 小于vs2012,此功能不能实现
return FALSE;
#endif
}
VOID VideoDXGICaptor::Deinit()
{
if (!m_bInit)
{
return;
}
#if _MSC_VER >= VS_VERSION
m_bInit = FALSE;
if (m_hDeskDupl)
{
m_hDeskDupl->Release();
m_hDeskDupl = NULL;
}
if (m_hDevice)
{
m_hDevice->Release();
m_hDevice = NULL;
}
if (m_hContext)
{
m_hContext->Release();
m_hContext = NULL;
}
#endif
}
BOOL VideoDXGICaptor::AttatchToThread(VOID)
{
if (g_bAttach)
{
return TRUE;
}
HDESK hCurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL);
if (!hCurrentDesktop)
{
return FALSE;
}
// Attach desktop to this thread
BOOL bDesktopAttached = SetThreadDesktop(hCurrentDesktop) != 0;
int r = GetLastError();
CloseDesktop(hCurrentDesktop);
hCurrentDesktop = NULL;
g_bAttach = TRUE;
return bDesktopAttached;
}
BOOL VideoDXGICaptor::CaptureImage(RECT &rect, void *pData, INT &nLen)
{
return QueryFrame(pData, nLen);
}
BOOL VideoDXGICaptor::CaptureImage(void *pData, INT &nLen)
{
return QueryFrame(pData, nLen);
}
BOOL VideoDXGICaptor::ResetDevice()
{
Deinit();
return Init();
}
void bgra2rgb24_2(char *src, int srclen, int srcw, int srch,
char *dst, int dstlen, int cpx, int cpy, int cpw, int cph)
{
for(int sh = cpy, dh = 0; dh < cph; sh++, dh++) {
for(int sw = cpx, dw = 0; dw < cpw; dw++, sw++) {
if((dh * cpw * 3 + (dw*3) + 2) >= dstlen){
qDebug()<<"error1"<<(dh * cpw * 3 + (dw*3) + 2);
return;
}
if((sh * srcw * 4 + (sw*4) + 2) >= srclen) {
qDebug()<<"error2"<<(sh * srcw * 4 + (sw*4) + 2);
return;
}
dst[dh * cpw * 3 + (dw*3) + 0] = src[sh * srcw * 4 + (sw*4) + 2];
dst[dh * cpw * 3 + (dw*3) + 1] = src[sh * srcw * 4 + (sw*4) + 1];
dst[dh * cpw * 3 + (dw*3) + 2] = src[sh * srcw * 4 + (sw*4) + 0];
}
}
}
BOOL VideoDXGICaptor::QueryFrame(void *pImgData, INT &nImgSize)
{
#if _MSC_VER >= VS_VERSION
if (!m_bInit || !AttatchToThread())
{
return FALSE;
}
nImgSize = 0;
IDXGIResource *hDesktopResource = NULL;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
HRESULT hr = m_hDeskDupl->AcquireNextFrame(500, &FrameInfo, &hDesktopResource);
printf("%d, %d\n", FrameInfo.PointerPosition.Position.x, FrameInfo.PointerPosition.Position.y);
fflush(stdout);
if (FAILED(hr))
{
//
// 在一些win10的系统上,如果桌面没有变化的情况下,
// 这里会发生超时现象,但是这并不是发生了错误,而是系统优化了刷新动作导致的。
// 所以,这里没必要返回FALSE,返回不带任何数据的TRUE即可
//
return TRUE;
}
//
// query next frame staging buffer
//
ID3D11Texture2D *hAcquiredDesktopImage = NULL;
hr = hDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&hAcquiredDesktopImage));
RESET_OBJECT(hDesktopResource);
if (FAILED(hr))
{
return FALSE;
}
//
// copy old description
//
D3D11_TEXTURE2D_DESC frameDescriptor;
hAcquiredDesktopImage->GetDesc(&frameDescriptor);
//
// create a new staging buffer for fill frame image
//
ID3D11Texture2D *hNewDesktopImage = NULL;
frameDescriptor.Usage = D3D11_USAGE_STAGING;
frameDescriptor.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
frameDescriptor.BindFlags = 0;
frameDescriptor.MiscFlags = 0;
frameDescriptor.MipLevels = 1;
frameDescriptor.ArraySize = 1;
frameDescriptor.SampleDesc.Count = 1;
hr = m_hDevice->CreateTexture2D(&frameDescriptor, NULL, &hNewDesktopImage);
if (FAILED(hr))
{
RESET_OBJECT(hAcquiredDesktopImage);
m_hDeskDupl->ReleaseFrame();
return FALSE;
}
//
// copy next staging buffer to new staging buffer
//
m_hContext->CopyResource(hNewDesktopImage, hAcquiredDesktopImage);
RESET_OBJECT(hAcquiredDesktopImage);
m_hDeskDupl->ReleaseFrame();
//
// create staging buffer for map bits
//
IDXGISurface *hStagingSurf = NULL;
hr = hNewDesktopImage->QueryInterface(__uuidof(IDXGISurface), (void **)(&hStagingSurf));
RESET_OBJECT(hNewDesktopImage);
if (FAILED(hr))
{
return FALSE;
}
//
// copy bits to user space
//
DXGI_MAPPED_RECT mappedRect;
hr = hStagingSurf->Map(&mappedRect, DXGI_MAP_READ);
if (SUCCEEDED(hr))
{
nImgSize = GetWidth() * GetHeight() * 4;
memcpy(pImgData, mappedRect.pBits, nImgSize);
//bgra2rgb24_2...
hStagingSurf->Unmap();
}
RESET_OBJECT(hStagingSurf);
return SUCCEEDED(hr);
#else
return FALSE;
#endif
}
int VideoDXGICaptor::GetWidth()
{
return m_iWidth;
}
int VideoDXGICaptor::GetHeight()
{
return m_iHeight;
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
ScreenCaptor.7z (2个子文件)
DXGICaptor.cpp 8KB
DXGICaptor.h 1KB
共 2 条
- 1
资源评论
- fas25hi2p41d12018-12-29初始化失败
- china_zyl2018-11-01嗯,,怎么说呢,,比较low,只能说新手当学习用可以..
- lcyw2018-10-14正好需要, 抓屏得到的数据是bgra的32位位图,如果要用x264编码压缩, 需要先转换成rgb24。 dxgi + mediafoundation coreApi 抓屏,采集摄像头,录音,一套全新的技术,基本上就抛弃 dshow了
- Z小偉2017-09-15没有用,无法把data里面的内容保存为图片。而且那个转化的函数参数没有说明。dai1994782018-03-13借地方解释一下,这个代码是抓屏用的,如果不懂得色彩空间,和深厚的c++基础,不要下载,下了也白瞎,免得说资源没用,回炉重造两年后再来看吧。谢谢dai1994782018-03-13void bgra2rgb24(char *src, int srclen, int srcw, int srch, char *dst, int dstlen, int cpx, int cpy, int cpw, int cph) 你需要什么参数说明?哪个参数的说明? rgb你想怎么保存?用fwrite可以吗?还是想保存成jpg?想保存成jpg自己下载libjpeg去啊!或者按ctrl+s啊! 祝你生活愉快,谢谢评价
dai199478
- 粉丝: 0
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功