How to get YUV422 Format from AMD GPU
PENG TONG
90
Reputation points
HRESULT Direct3DDevice::VideoProcessInit(UINT width, UINT height)
{
Logger::Write(LogLevel::LOG_INFO, L"VideoProcessInit");
HRESULT hr;
hr = Device->QueryInterface(IID_PPV_ARGS(&VideoDevice));
if(FAILED(hr))
{
Logger::Write(LogLevel::LOG_INFO, L"Failed to get ID3D11VideoDevice");
return hr;
}
else
{
Logger::Write(LogLevel::LOG_INFO, L"Pass to get ID3D11VideoDevice");
}
hr = DeviceContext->QueryInterface(IID_PPV_ARGS(&VideoContext));
if (FAILED(hr))
{
Logger::Write(LogLevel::LOG_INFO, L"Failed to get ID3D11VideoContext");
return hr;
}
else
{
Logger::Write(LogLevel::LOG_INFO, L"Pass to get ID3D11VideoContext");
}
D3D11_VIDEO_PROCESSOR_CONTENT_DESC contentDesc = {};
contentDesc.InputFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
contentDesc.InputWidth = width;
contentDesc.InputHeight = height;
contentDesc.OutputWidth = width;
contentDesc.OutputHeight = height;
contentDesc.Usage = D3D11_VIDEO_USAGE_OPTIMAL_QUALITY;
hr = VideoDevice->CreateVideoProcessorEnumerator(&contentDesc, &Enumerator);
if(FAILED(hr))
{
Logger::Write(LogLevel::LOG_INFO, L"Failed to create video processor enumerator");
return hr;
}
else
{
Logger::Write(LogLevel::LOG_INFO, L"Pass to create video processor enumerator");
}
hr = VideoDevice->CreateVideoProcessor(Enumerator.Get(), 0, &VideoProcessor);
if(FAILED(hr))
{
Logger::Write(LogLevel::LOG_INFO, L"Failed to create video processor");
return hr;
}
else
{
Logger::Write(LogLevel::LOG_INFO, L"Pass to create video processor");
}
D3D11_TEXTURE2D_DESC outputDesc = {};
outputDesc.Width = width;
outputDesc.Height = height;
outputDesc.MipLevels = 1;
outputDesc.ArraySize = 1;
outputDesc.Format = DXGI_FORMAT_YUY2;
outputDesc.SampleDesc.Count = 1;
outputDesc.SampleDesc.Quality = 0;
outputDesc.Usage = D3D11_USAGE_DEFAULT;
outputDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
outputDesc.CPUAccessFlags = 0;
outputDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
hr = Device->CreateTexture2D(&outputDesc, nullptr, &OutputTexture);
if(FAILED(hr))
{
Logger::Write(LogLevel::LOG_INFO, L"Failed to create YUY2 output texture");
return hr;
}
else
{
Logger::Write(LogLevel::LOG_INFO, L"Pass to create YUY2 output texture");
}
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outputViewDesc = {};
outputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
outputViewDesc.Texture2D.MipSlice = 0;
hr = VideoDevice->CreateVideoProcessorOutputView(OutputTexture.Get(), Enumerator.Get(), &outputViewDesc, &OutputView);
if(FAILED(hr))
{
Logger::Write(LogLevel::LOG_INFO, L"Failed to create video processor output view");
return hr;
}
else
{
Logger::Write(LogLevel::LOG_INFO, L"Pass to create video processor output view");
}
D3D11_VIDEO_PROCESSOR_COLOR_SPACE srcColorSpace = {};
srcColorSpace.Usage = 0;
srcColorSpace.RGB_Range = 0;
srcColorSpace.YCbCr_Matrix = 0;
srcColorSpace.YCbCr_xvYCC = 0;
D3D11_VIDEO_PROCESSOR_COLOR_SPACE dstColorSpace = {};
dstColorSpace.Usage = 0;
dstColorSpace.RGB_Range = 0;
dstColorSpace.YCbCr_Matrix = 1;
dstColorSpace.YCbCr_xvYCC = 0;
dstColorSpace.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255; // TV范围
VideoContext->VideoProcessorSetStreamColorSpace(VideoProcessor.Get(), 0, &srcColorSpace);
VideoContext->VideoProcessorSetOutputColorSpace(VideoProcessor.Get(), &dstColorSpace);
RECT destRect = {0, 0, static_cast<LONG>(width), static_cast<LONG>(height) };
RECT srcRect = destRect;
VideoContext->VideoProcessorSetOutputTargetRect(VideoProcessor.Get(), TRUE, &destRect);
VideoContext->VideoProcessorSetStreamDestRect(VideoProcessor.Get(), 0, TRUE, &destRect);
VideoContext->VideoProcessorSetStreamSourceRect(VideoProcessor.Get(), 0, TRUE, &srcRect);
D3D11_VIDEO_COLOR backgroundColor = {};
backgroundColor.RGBA.A = 1.0f;
backgroundColor.RGBA.R = 0.0f;
backgroundColor.RGBA.G = 0.0f;
backgroundColor.RGBA.B = 0.0f;
VideoContext->VideoProcessorSetOutputBackgroundColor(VideoProcessor.Get(), TRUE, &backgroundColor);
return S_OK;
}
HRESULT Direct3DDevice::RebuildVideoProcessorIfNeeded(UINT width, UINT height)
{
if (width == 0 || height == 0) return E_INVALIDARG;
{
std::lock_guard<std::mutex> lock(VideoProcMutex);
if (IsVideoProcessorValid && CurrentWidth == width && CurrentHeight == height)
return S_OK;
Logger::Write(LogLevel::LOG_INFO, L"IsVideoProcessorValid is true");
// Release old resources
VideoProcessor.Reset();
OutputView.Reset();
OutputTexture.Reset();
Enumerator.Reset();
// Reinitialize video processor with new size
HRESULT hr = VideoProcessInit(width, height);
if(SUCCEEDED(hr))
{
CurrentWidth = width;
CurrentHeight = height;
IsVideoProcessorValid = true;
Logger::Write(LogLevel::LOG_INFO, L"VideoProcessInit is pass");
}
else
{
IsVideoProcessorValid = false;
Logger::Write(LogLevel::LOG_ERROR, L"Failed to rebuild video processor for " +
Logger::number2wstring(width) + L"x" + Logger::number2wstring(height) + L" " +Logger::hex2wstring(hr));
}
return hr;
}
}
Using the above code,I can obtain YUV422 format frames on the Intel integrated graphics platform. For AMD independent graphics cards, it is failed for Device->CreateTexture2D(&outputDesc, nullptr, &OutputTexture). I set outputDesc.BindFlags = 0, It is failed for VideoDevice->CreateVideoProcessorOutputView(OutputTexture.Get(), Enumerator.Get(), &outputViewDesc, &OutputView);
Windows development | Windows Driver Kit (WDK)
Sign in to answer