VideoProcessor render NV12 format Texture2D have wrong result (blurred screen)

Grey 5 Reputation points
2023-03-23T08:35:37.9+00:00

I want to use D3D11 VideoProcessor to render a decoded video, but i found when video's height is like 1080, 360, such as height cannot satisfy mod16, the render result will be blurred screen, but 720, 4k will be ok.

I tried to input a 1080p bmp file and convert to nv12 format then copy to GPU texture2D, same result.

1080p render result

Here is my sample code, just similiar with Windows-classic-samples DX11VideoRenderer.

By the way, i also tested DX11VideoRenderer with topoedit, the 1080p video render result is normal, so i copy the frame texture from GPU to CPU and convert to ARGB then saved to bmp file, the bmp file is similiar with above photo.

I don't know how this happened, maybe something about data structuring. Is there a method to map NV12 data from 1080p frame to texture2d buffer correctly?

HRESULT CD3D11VideoProcessor::ProcessImagePresent(CWICBitmap& cWICBitmap)
{
	HRESULT hr = S_OK;
	ID3D11VideoProcessorInputView* pD3D11VideoProcessorInputViewIn = NULL;
	ID3D11VideoProcessorOutputView* pD3D11VideoProcessorOutputView = NULL;
	ID3D11VideoDevice* pD3D11VideoDevice = NULL;
	ID3D11Texture2D* pInTexture2D = NULL;
	ID3D11Texture2D* pOutTexture2D = NULL;

	IF_FAILED_RETURN(m_pD3D11VideoContext == NULL ? E_UNEXPECTED : S_OK);

	try
	{
		IF_FAILED_THROW(m_pD3D11Device->QueryInterface(__uuidof(ID3D11VideoDevice), reinterpret_cast<void**>(&pD3D11VideoDevice)));

		D3D11_TEXTURE2D_DESC desc2D;
		desc2D.Width = cWICBitmap.GetWidth();
		desc2D.Height = cWICBitmap.GetHeight();
		desc2D.MipLevels = 1;
		desc2D.ArraySize = 1;
		desc2D.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
		desc2D.SampleDesc.Count = 1;
		desc2D.SampleDesc.Quality = 0;
		desc2D.Usage = D3D11_USAGE_DEFAULT;
		desc2D.BindFlags = D3D11_BIND_RENDER_TARGET;
		desc2D.CPUAccessFlags = 0;
		desc2D.MiscFlags = 0;

		IF_FAILED_THROW(cWICBitmap.Create2DTextureFromBitmap(m_pD3D11Device, &pInTexture2D, desc2D));

		desc2D.Format = DXGI_FORMAT_NV12;

		IF_FAILED_THROW(m_pD3D11Device->CreateTexture2D(&desc2D, NULL, &pOutTexture2D));



		D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC pInDesc;
		ZeroMemory(&pInDesc, sizeof(pInDesc));
		pInDesc.FourCC = 0;
		pInDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
		pInDesc.Texture2D.MipSlice = 0;
		pInDesc.Texture2D.ArraySlice = 0;

		D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC pOutDesc;
		ZeroMemory(&pOutDesc, sizeof(pOutDesc));
		pOutDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
		pOutDesc.Texture2D.MipSlice = 0;

		// process to present
		D3D11_MAPPED_SUBRESOURCE MappedSubResource;
		UINT uiSubResource = D3D11CalcSubresource(0, 0, 0);
		ID3D11Texture2D* pARGBTexture = NULL;
		pInTexture2D->GetDesc(&desc2D);
		desc2D.BindFlags = 0;
		desc2D.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
		desc2D.Usage = D3D11_USAGE_STAGING;
		desc2D.MiscFlags = 0;

		IF_FAILED_THROW(m_pD3D11Device->CreateTexture2D(&desc2D, NULL, &pARGBTexture));
		m_pD3D11DeviceContext->CopyResource(pARGBTexture, pInTexture2D);
		IF_FAILED_THROW(m_pD3D11DeviceContext->Map(pARGBTexture, uiSubResource, D3D11_MAP_READ, 0, &MappedSubResource));
		BYTE* src = new BYTE[desc2D.Width * desc2D.Height * 6 / 4];
		BYTE* src_y = src;
		BYTE* src_uv = src_y + desc2D.Width * desc2D.Height;
		libyuv::ARGBToNV12((BYTE*)MappedSubResource.pData, MappedSubResource.RowPitch,
						   src_y, desc2D.Width,
						   src_uv, desc2D.Width,
						   desc2D.Width, desc2D.Height);
		m_pD3D11DeviceContext->Unmap(pARGBTexture, uiSubResource);
		SAFE_RELEASE(pARGBTexture);

		// create nv12 texture
		ID3D11Texture2D* pNV12Texture = NULL;
		desc2D.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		desc2D.Usage = D3D11_USAGE_STAGING;
		desc2D.MiscFlags = 0;
		desc2D.Format = DXGI_FORMAT_NV12;
		IF_FAILED_THROW(m_pD3D11Device->CreateTexture2D(&desc2D, NULL, &pNV12Texture));
		IF_FAILED_THROW(m_pD3D11DeviceContext->Map(pNV12Texture, uiSubResource, D3D11_MAP_WRITE, 0, &MappedSubResource));
		BYTE* dst = (BYTE*)MappedSubResource.pData;
		memcpy(dst, src, desc2D.Width * desc2D.Height * 6 / 4);
		m_pD3D11DeviceContext->Unmap(pNV12Texture, uiSubResource);

		SAFE_DELETE(src);

		m_pD3D11DeviceContext->CopyResource(pOutTexture2D, pNV12Texture);

		RenderNV12Texture(pOutTexture2D);
		ID3D11Texture2D* dxgi_back_buffer = NULL;
		hr = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&dxgi_back_buffer);

		IF_FAILED_THROW(pD3D11VideoDevice->CreateVideoProcessorInputView(pOutTexture2D, m_pD3D11VideoProcessorEnumerator, &pInDesc, &pD3D11VideoProcessorInputViewIn));
		IF_FAILED_THROW(pD3D11VideoDevice->CreateVideoProcessorOutputView(dxgi_back_buffer, m_pD3D11VideoProcessorEnumerator, &pOutDesc, &pD3D11VideoProcessorOutputView));

		D3D11_VIDEO_PROCESSOR_STREAM stream_data;
		ZeroMemory(&stream_data, sizeof(stream_data));
		stream_data.Enable = TRUE;
		stream_data.OutputIndex = 0;
		stream_data.InputFrameOrField = 0;
		stream_data.PastFrames = 0;
		stream_data.FutureFrames = 0;
		stream_data.ppPastSurfaces = nullptr;
		stream_data.ppFutureSurfaces = nullptr;
		stream_data.pInputSurface = pD3D11VideoProcessorInputViewIn;
		stream_data.ppPastSurfacesRight = nullptr;
		stream_data.ppFutureSurfacesRight = nullptr;
		stream_data.pInputSurfaceRight = nullptr;

		IF_FAILED_THROW(m_pD3D11VideoContext->VideoProcessorBlt(m_pD3D11VideoProcessor, pD3D11VideoProcessorOutputView, 0, 1, &stream_data));
		hr = m_SwapChain->Present(1, 0);

		SAFE_RELEASE(pNV12Texture);
		SAFE_RELEASE(dxgi_back_buffer);
	}
	catch (HRESULT) {}

	SAFE_RELEASE(pOutTexture2D);
	SAFE_RELEASE(pInTexture2D);
	SAFE_RELEASE(pD3D11VideoProcessorOutputView);
	SAFE_RELEASE(pD3D11VideoProcessorInputViewIn);
	SAFE_RELEASE(pD3D11VideoDevice);

	return hr;
}
Windows 10
Windows 10
A Microsoft operating system that runs on personal computers and tablets.
10,617 questions
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,422 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,527 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Limitless Technology 43,931 Reputation points
    2023-03-23T16:15:38.41+00:00

    Hello there,

    This format differs from DXGI_FORMAT_NV12 in that the layout of the data within the resource is completely opaque to applications. Applications cannot use the CPU to map the resource and then access the data within the resource. You cannot use shaders with this format.

    In Dxva2Renderer.cpp, check for HANDLE_DIRECTX_ERROR_UNDOCUMENTED.

    A list of modifiers at the bottom of the page more fully describes each format type. https://learn.microsoft.com/en-gb/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format

    Hope this resolves your Query !!

    --If the reply is helpful, please Upvote and Accept it as an answer–