Add support for decoding NV12 into RGB image

This commit is contained in:
Wojtek Figat
2024-05-15 11:15:19 +02:00
parent 9d2dc91920
commit 82bf4238df
6 changed files with 75 additions and 15 deletions

View File

@@ -297,6 +297,7 @@ struct GPUDevice::PrivateData
GPUPipelineState* PS_CopyLinear = nullptr;
GPUPipelineState* PS_Clear = nullptr;
GPUPipelineState* PS_DecodeYUY2 = nullptr;
GPUPipelineState* PS_DecodeNV12 = nullptr;
GPUBuffer* FullscreenTriangleVB = nullptr;
AssetReference<Material> DefaultMaterial;
SoftAssetReference<Material> DefaultDeformableMaterial;
@@ -715,6 +716,18 @@ GPUPipelineState* GPUDevice::GetDecodeYUY2PS() const
return _res->PS_DecodeYUY2;
}
GPUPipelineState* GPUDevice::GetDecodeNV12PS() const
{
if (_res->PS_DecodeNV12 == nullptr)
{
auto psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
psDesc.PS = QuadShader->GetPS("PS_DecodeNV12");
_res->PS_DecodeNV12 = const_cast<GPUDevice*>(this)->CreatePipelineState();
_res->PS_DecodeNV12->Init(psDesc);
}
return _res->PS_DecodeNV12;
}
GPUBuffer* GPUDevice::GetFullscreenTriangleVB() const
{
return _res->FullscreenTriangleVB;

View File

@@ -275,6 +275,11 @@ public:
/// </summary>
GPUPipelineState* GetDecodeYUY2PS() const;
/// <summary>
/// Gets the shader pipeline state object for NV12 frame decoding to RGBA.
/// </summary>
GPUPipelineState* GetDecodeNV12PS() const;
/// <summary>
/// Gets the fullscreen-triangle vertex buffer.
/// </summary>

View File

@@ -253,7 +253,7 @@ namespace MF
IMF2DBuffer* buffer2D = nullptr;
BYTE* bufferData = nullptr;
LONG bufferStride = 0;
if (isVideo && sample->GetBufferByIndex(0, &buffer) == S_OK && buffer->QueryInterface(IID_PPV_ARGS(&buffer2D)) == S_OK)
if (isVideo && player.Format != PixelFormat::NV12 && sample->GetBufferByIndex(0, &buffer) == S_OK && buffer->QueryInterface(IID_PPV_ARGS(&buffer2D)) == S_OK)
{
LONG bufferPitch = 0;
hr = buffer2D->Lock2D(&bufferData, &bufferPitch);

View File

@@ -91,8 +91,19 @@ protected:
context->GPU->SetViewportAndScissors((float)_player->Width, (float)_player->Height);
context->GPU->SetRenderTarget(frame->View());
context->GPU->BindSR(0, _player->FrameUpload->View());
ASSERT_LOW_LAYER(_player->Format == PixelFormat::YUY2);
context->GPU->SetState(GPUDevice::Instance->GetDecodeYUY2PS());
GPUPipelineState* pso;
switch (_player->Format)
{
case PixelFormat::YUY2:
pso = GPUDevice::Instance->GetDecodeYUY2PS();
break;
case PixelFormat::NV12:
pso = GPUDevice::Instance->GetDecodeNV12PS();
break;
default:
return Result::Failed;
}
context->GPU->SetState(pso);
context->GPU->DrawFullscreenTriangle();
}
else