NV12 纹理在 DirectX 11.1 中不起作用
NV12 textures not working in DirectX 11.1
我正在尝试使用 DirectX 11.1 从使用 ffmpeg 2.8.11 解码的帧渲染 NV12 纹理,但当我渲染它们时,纹理被破坏并且颜色总是关闭。
结果是 :https://i.stack.imgur.com/8bnhT.jpg
下面的代码是我如何通过 ffmpeg 解码YUV420P格式的帧,然后通过交错 U 和 V 平面将(不确定)转换为 NV12 格式。
static uint8_t *pixelsPtr_ = nullptr;
UINT rowPitch = ((width + 1) >> 1) * 2;
UINT imageSize = (rowPitch * height) + ((rowPitch * height + 1) >> 1);
if (!pixelsPtr_)
{
pixelsPtr_ = new uint8_t[imageSize];
}
int j, position = 0;
uint32_t pitchY = avFrame.linesize[0];
uint32_t pitchU = avFrame.linesize[1];
uint32_t pitchV = avFrame.linesize[2];
uint8_t *avY = avFrame.data[0];
uint8_t *avU = avFrame.data[1];
uint8_t *avV = avFrame.data[2];
::SecureZeroMemory(pixelsPtr_, imageSize);
for (j = 0; j < height; j++)
{
::CopyMemory(pixelsPtr_ + position, avY, (width));
position += (width);
avY += pitchY;
}
for (j = 0; j < height >> 1; j++)
{
::CopyMemory(pixelsPtr_ + position, avU, (width >> 1));
position += (width >> 1);
avU += pitchU;
::CopyMemory(pixelsPtr_ + position, avV, (width >> 1));
position += (width >> 1);
avV += pitchV;
}
这就是我用刚刚获得的数据创建Texture2D的方式。
// Create texture
D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_NV12;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = pixelsPtr_;
initData.SysMemPitch = rowPitch;
ID3D11Texture2D* tex = nullptr;
hr = d3dDevice->CreateTexture2D(&desc, &initData, &tex);
if (SUCCEEDED(hr) && tex != 0)
{
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
memset(&SRVDesc, 0, sizeof(SRVDesc));
SRVDesc.Format = DXGI_FORMAT_R8_UNORM;
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
SRVDesc.Texture2D.MipLevels = 1;
hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, &textureViewYUV[0]);
if (FAILED(hr))
{
tex->Release();
return hr;
}
SRVDesc.Format = DXGI_FORMAT_R8G8_UNORM;
hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, &textureViewYUV[1]);
if (FAILED(hr))
{
tex->Release();
return hr;
}
tex->Release();
}
然后我将两个着色器资源视图传递给像素着色器
graphics->Context()->PSSetShaderResources(0, 2, textureViewYUV);
这是像素着色器:
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float4 Color : COLOR;
float2 texCoord : TEXCOORD;
};
static const float3x3 YUVtoRGBCoeffMatrix =
{
1.164383f, 1.164383f, 1.164383f,
0.000000f, -0.391762f, 2.017232f,
1.596027f, -0.812968f, 0.000000f
};
Texture2D<float> luminanceChannel;
Texture2D<float2> chrominanceChannel;
SamplerState linearfilter
{
Filter = MIN_MAG_MIP_LINEAR;
};
float3 ConvertYUVtoRGB(float3 yuv)
{
// Derived from https://msdn.microsoft.com/en-us/library/windows/desktop/dd206750(v=vs.85).aspx
// Section: Converting 8-bit YUV to RGB888
// These values are calculated from (16 / 255) and (128 / 255)
yuv -= float3(0.062745f, 0.501960f, 0.501960f);
yuv = mul(yuv, YUVtoRGBCoeffMatrix);
return saturate(yuv);
}
float4 main(PixelShaderInput input) : SV_TARGET
{
float y = luminanceChannel.Sample(linearfilter, input.texCoord);
float2 uv = chrominanceChannel.Sample(linearfilter, input.texCoord);
float3 YUV = float3(y, uv.x, uv.y);
float4 YUV4 = float4(YUV.x, YUV.y, YUV.z, 1);
float3 RGB = ConvertYUVtoRGB(YUV);
float4 RGB4 = float4(RGB.x, RGB.y, RGB.z, 1);
return RGB4;
}
有人可以帮助我吗?我做错了什么?
编辑 #1
int skipLineArea = 0;
int uvCount = (height >> 1) * (width >> 1);
for (j = 0, k = 0; j < uvCount; j++, k++)
{
if (skipLineArea == (width >> 1))
{
k += pitchU - (width >> 1);
skipLineArea = 0;
}
pixelsPtr_[position++] = avU[k];
pixelsPtr_[position++] = avV[k];
skipLineArea++;
}
编辑#2
更新纹理而不是创建新纹理
D3D11_MAPPED_SUBRESOURCE mappedResource;
d3dContext->Map(tex, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
uint8_t* mappedData = reinterpret_cast<uint8_t*>(mappedResource.pData);
for (UINT i = 0; i < height * 1.5; ++i)
{
memcpy(mappedData, frameData, rowPitch);
mappedData += mappedResource.RowPitch;
frameData += rowPitch;
}
d3dContext->Unmap(tex, 0);
NV12
格式不会分隔U
值和V
值。它们是交错的 NV12 格式。您应该使用IMC4
纹理格式。或者,可以将复制代码更改为交错U
和V
值。
相关文章:
- 我的神经网络不起作用 [XOR 问题]
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- C++为什么尽管我调用了void函数,它却不起作用
- 为什么在保护模式下继承升级不起作用
- 循环在计数器中不起作用
- 在其他文件中创建类时在 c++ 项目中不起作用
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- 为什么二进制搜索在我的测试中不起作用
- 我的代码中有错误吗?使用BGI图形的C++代码对我不起作用
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- Bjarne Stroustrup Book - std_lib_facilities.h - 不起作用(未知类型名称)
- 为什么简单的算术减法在"if"条件下不起作用?
- 为什么Stroustup书中的has_f不起作用
- 你能检查一下为什么在这个代码中从链接列表中删除项目不起作用吗
- NV12 纹理在 DirectX 11.1 中不起作用
- DirectX 呈现参数窗口=假不起作用
- Awesomium with Directx 9 HWND 不起作用
- 深度模板不起作用-DirectX 10 C