DirectComposition & FFmpeg的两种实现方法

导读

本文适合对FFmpeg和DX有所了解的新手。

以下的文章包括从FFmpeg解码到DirectComposition上屏的两种实现方式。

正文

一、利用SwapChain上屏

1.创建设备并绑定交换链

//创建DXGI工厂
ComPtr<IDXGIFactory4> factory;
CreateDXGIFactory1(IID_PPV_ARGS(&factory));

//创建D3D设备
D3D_FEATURE_LEVEL featureLevelSupported;
D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, d3dDevice.GetAddressOf(), &featureLevelSupported, nullptr);

ComPtr<IDXGIDevice> dxgiDevice;
d3dDevice.As(&dxgiDevice);

//创建DirectComposition设备
ComPtr<IDCompositionDesktopDevice>	pDcomDevice;
DCompositionCreateDevice3(dxgiDevice.Get(), IID_PPV_ARGS(&pDcomDevice));

// 交换链描述符
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
		swapChainDesc.BufferCount = 2;
		swapChainDesc.Width = m_width;
		swapChainDesc.Height = m_height;
		swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT |                 
        DXGI_USAGE_BACK_BUFFER;
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
		swapChainDesc.SampleDesc.Count = 1;
		swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;

//创建交换链
ComPtr<IDXGISwapChain1> swapChain;
HRESULT hr = (factory->CreateSwapChainForComposition(
			d3dDevice.Get(),
			&swapChainDesc,
			nullptr,
			&swapChain
		));

//根据窗口句柄创建DirectCompositionTarget
pDcomDevice->CreateTargetForHwnd(m_hWnd,true, m_target.ReleaseAndGetAddressOf());
//创建Visual
pDcomDevice->CreateVisual(m_visual.ReleaseAndGetAddressOf());
//visual绑定交换链
m_visual->SetContent(swapChain.Get());
//设置根visual
m_target->SetRoot(m_visual.Get());
pDcomDevice->Commit();

2.更新交换链缓冲区实现上屏

//获取D3D设备上下文
ComPtr<ID3D11DeviceContext> pContext;
d3dDevice->GetImmediateContext(pContext.ReleaseAndGetAddressOf());

//获取交换链缓冲区
ComPtr<IDXGISurface> surface;
m_swapChain->GetBuffer(0, __uuidof(IDXGISurface), reinterpret_cast<void**>(surface.GetAddressOf()));

ComPtr<ID3D11Texture2D> dc;
surface.As(&dc);

//拷贝纹理到交换链缓冲区
pContext->CopyResource(dc.Get(), m_pD3DTexture.Get());

//上屏
m_swapChain->Present(1, 0);

二、利用DCompositionSurface上屏

1.创建设备并绑定DirectCompositionSurface

//创建DXGI工厂
ComPtr<IDXGIFactory4> factory;
CreateDXGIFactory1(IID_PPV_ARGS(&factory));

//创建D3D设备
D3D_FEATURE_LEVEL featureLevelSupported;
D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, d3dDevice.GetAddressOf(), &featureLevelSupported, nullptr);

ComPtr<IDXGIDevice> dxgiDevice;
d3dDevice.As(&dxgiDevice);

//创建d2d设备
ComPtr<ID2D1Device> d2dDevice;   
D2D1CreateDevice(dxgiDevice.Get(),D2D1::CreationProperties(D2D1_THREADING_MODE_SINGLE_THREADED, D2D1_DEBUG_LEVEL_NONE,
                                                  D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS), &d2dDevice);

//利用d2d设备创建DirectComposition设备
ComPtr<IDCompositionDesktopDevice>	pDcomDevice;
DCompositionCreateDevice3(d2dDevice.Get(), IID_PPV_ARGS(&pDcomDevice));

//创建DCompositionSurface
pDcomDevice->CreateVirtualSurface(m_width, m_height, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_ALPHA_MODE_PREMULTIPLIED, &m_surface);
//根据窗口句柄创建DirectCompositionTarget
pDcomDevice->CreateTargetForHwnd(m_hWnd,true, m_target.ReleaseAndGetAddressOf());
//创建Visual
pDcomDevice->CreateVisual(m_visual.ReleaseAndGetAddressOf());
//visual绑定交换链
m_visual->SetContent(m_surface.Get());
//设置根visual
m_target->SetRoot(m_visual.Get());
pDcomDevice->Commit();

 2.ID3D11Texture2D转ID2D1Bitmap

//用于内存映射的纹理
ComPtr<ID3D11Texture2D> pTempTex;
D3D11_TEXTURE2D_DESC texDesc;
m_pD3DTexture->GetDesc(&texDesc);
texDesc.BindFlags = 0;
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;    //CPU可读
texDesc.Usage = D3D11_USAGE_STAGING;

m_pd3dDevice->CreateTexture2D(&texDesc, NULL, pTempTex.GetAddressOf());
                 m_pd3dDeviceContex->CopyResource(pTempTex.Get(), m_pD3DTexture.Get());
                 D3D11_MAPPED_SUBRESOURCE mappedResource;

//内存映射
m_pd3dDeviceContex->Map(pTempTex.Get(), 0, D3D11_MAP_READ, 0, &mappedResource);
 
//一幅待显示位图
ComPtr<ID2D1Bitmap> pBmp; 
POINT offset = {0, 0};
ComPtr<ID2D1DeviceContext> dc;
//BeginDraw返回d2d设备上下文,需要注意Surface与D2D设备关联
m_pDCompSurface->BeginDraw(nullptr, IID_PPV_ARGS(&dc), &offset);

//d2d渲染对象
ComPtr<ID2D1RenderTarget> pRT;
dc.As(&pRT);
//设置一些位图属性
D2D1_SIZE_U size = D2D1::SizeU(texDesc.Width, texDesc.Height);
D2D1_BITMAP_PROPERTIES bmpprops;
bmpprops.dpiX = 96.0f;
bmpprops.dpiY = 96.0f;
bmpprops.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
bmpprops.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
//创建一张空的位图
pRT->CreateBitmap(size, bmpprops, m_pBmp.ReleaseAndGetAddressOf());
                     m_pDCompSurface->EndDraw();}
 
D2D1_RECT_U rc = {0, 0, nWidth, nHeight};
//将纹理上的数据拷贝到位图
pBmp->CopyFromMemory(&rc, mappedResource.pData, mappedResource.RowPitch);

m_pd3dDeviceContex->Unmap(pTempTex.Get(), 0);

3.利用ID2D1Bitmap上屏

POINT offset = {0, 0};
ComPtr<ID2D1DeviceContext> dc;
//返回d2d设备上下文
m_pDCompSurface->BeginDraw(nullptr, IID_PPV_ARGS(&dc), &offset);

if(dc)
{
    D2D1_RECT_F rcBmp = {0, 0, m_width, m_height};
    //2d画图
    dc->DrawBitmap(m_pBmp.Get(), rcBmp);
}
m_pDCompSurface->EndDraw();
//提交命令,合成图像
m_pDCompDevice->Commit();

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值