【音视频】WIN8|WIN10的桌面采集技术-DXGI(一)

本篇文章是本人音视频技术文章集中的开篇,之后会持续更新创作更多关于音视频的文章。望有大佬可以交流、指点。
文章主要表现形式是以实现为主,扩展知识为辅,所以一般比较长,不过也有更多实现细节以供参考。

技术简介

DXGI(Microsoft DirectX Graphics Infrastructure)是微软提供的一种可以在win8及以上系统使用的图形设备接口。它负责枚举图形适配器、枚举显示模式、选择缓冲区格式、在进程之间(例如,在应用程序和桌面窗口管理器(DWM)之间)共享资源,以及将呈现的帧传给窗口或监视器以供显示。其直接和硬件设备进行交互,具有很高的效率和性能。
Direct3D 10、Direct3D 11和Direct3D 12等都使用DXGI技术。

使用模块(库)

本篇代码中使用到了d3d11和dxgi两个dll库。

主要流程和代码

1、加载d3d11和dxgi库,并初始化d3d设备。

int DuplicationCaptor::init(const DesktopCaptureRect& rect, const int fps)
{
   
	int err = ERROR_CODE_OK;
	if (m_inited) {
   
		return err;
	}

	do {
   
		m_d3d = HELPER::SystemLib::loadSystemLib("d3d11.dll");
		if (m_d3d == nullptr) {
   
			err = ERROR_CODE_D3D_LOAD_LIB_FAILED;
			break;
		}
		m_dxgi = HELPER::SystemLib::loadSystemLib("dxgi.dll");
		if (m_dxgi == nullptr) {
   
			err = ERROR_CODE_DXGI_LOAD_LIB_FAILED;
			break;
		}

		err = initD3d();
		HCMDR_ERROR_CODE_BREAK(err);

		m_timebase = {
    1, AV_TIME_BASE };
		m_pixelFmt = AV_PIX_FMT_BGRA;
		m_rect = rect;
		m_fps = fps;
		m_width = rect.right - rect.left;
		m_height = rect.bottom - rect.top;
		m_bufferSize = (m_width * 32 + 31) / 32 * m_height * 4;
		m_buffer = new uint8_t[m_bufferSize];

		m_inited = true;
	} while (0);

	if (err != ERROR_CODE_OK) {
   
		LOGGER::Logger::log(LOGGER::LOG_TYPE_ERROR, "[%s] msg: %s, last error: %lu", __FUNCTION__,
			HCMDR_GET_ERROR_DESC(err), GetLastError());
		cleanup();
	}

	return err;
}

init中d3d设备初始化函数:

int DuplicationCaptor::initD3d()
{
   
	int err = ERROR_CODE_OK;
	do {
   
		IDXGIAdapter* adapter = nullptr;
		err = getAdapter(&adapter);
		HCMDR_ERROR_CODE_BREAK(err);

		err = createD3dDevice(adapter, &m_d3dDevice);
		HCMDR_ERROR_CODE_BREAK(err);
	} while (0);

	return err;
}

initD3d中获取适配器函数:

int DuplicationCaptor::getAdapter(IDXGIAdapter** adapter)
{
   
	int err = ERROR_CODE_OK;

	do {
   
		std::list<IDXGIAdapter*> adapters;
		err = getAdapters(adapters);
		HCMDR_ERROR_CODE_BREAK(err);
		if (adapters.empty()) {
   
			err = ERROR_CODE_DXGI_FOUND_ADAPTER_FAILED;
			break;
		}

		for (std::list<IDXGIAdapter*>::iterator it = adapters.begin(); it != adapters.end(); it++) {
   
			IDXGIOutput* adapterOutput = nullptr;
			DXGI_ADAPTER_DESC adapterDesc = {
    0 };
			(*it)->GetDesc(&adapterDesc);
			for (UINT i = 0; (*it)->EnumOutputs(i, &adapterOutput) != DXGI_ERROR_NOT_FOUND; i++) {
   
				DXGI_OUTPUT_DESC outputDesc = {
    0 };
				RECT outputRect = {
    0 };
				HRESULT hr = adapterOutput->GetDesc(&outputDesc);
				if (FAILED(hr)) {
   
					continue;
				}

				outputRect = outputDesc.DesktopCoordinates;
				// The target area is within the selected area
				if (m_rect.left >= outputRect.left && m_rect.top >= outputRect.top &&
					m_rect.right <= outputRect.right && m_rect.bottom <= outputRect.bottom) {
   
					break;
				}
			}

			if (err == ERROR_CODE_OK) {
   
				*adapter = *it;
				break;
			}
		}
	} while (0);

	return err;
}

getAdapter中获取适配器列表函数:

int DuplicationCaptor::getAdapters(std::list<IDXGIAdapter*>& adapters)
{
   
	int err = ERROR_CODE_OK;

	do {
   
		DXGI_CREATE_FACTORY1 createFactory1 = (DXGI_CREATE_FACTORY1)GetProcAddress(m_dxgi, "CreateDXGIFactory1");
		if (createFactory1 == nullptr) {
   
			err = ERROR_CODE_DXGI_GET_PROC_FAILED;
			break;
		}

		IDXGIFactory1* factory1 = nullptr;
		HRESULT hr = createFactory1(__uuidof(IDXGIFactory1), &factory1);
		if (FAILED(hr)) {
   
			err = ERROR_CODE_DXGI_GET_FACTORY_FAILED;
			break;
		}

		IDXGIAdapter* adapter = nullptr;
		adapters.clear();
		for (UINT i = 0; factory1->EnumAdapters(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++) {
   
			if (adapter != nullptr
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值