[host] added YUV420 output support

This commit is contained in:
Geoffrey McRae 2018-07-28 06:15:55 +10:00
parent 2a03d1c4a9
commit e515cdc8dd
10 changed files with 339 additions and 177 deletions

View file

@ -27,7 +27,7 @@ typedef enum FrameType
{ {
FRAME_TYPE_INVALID , FRAME_TYPE_INVALID ,
FRAME_TYPE_ARGB , // ABGR interleaved: A,R,G,B 32bpp FRAME_TYPE_ARGB , // ABGR interleaved: A,R,G,B 32bpp
FRAME_TYPE_NV12 , // NV12 FRAME_TYPE_YUV420 , // YUV420
FRAME_TYPE_H264 , // H264 compressed FRAME_TYPE_H264 , // H264 compressed
FRAME_TYPE_MAX , // sentinel value FRAME_TYPE_MAX , // sentinel value
} }

View file

@ -30,7 +30,6 @@ DXGI::DXGI() :
m_device(), m_device(),
m_deviceContext(), m_deviceContext(),
m_dup(), m_dup(),
m_texture(),
m_pointer(NULL) m_pointer(NULL)
{ {
} }
@ -152,8 +151,8 @@ bool DXGI::Initialize(CaptureOptions * options)
m_frameType = FRAME_TYPE_ARGB; m_frameType = FRAME_TYPE_ARGB;
for(CaptureOptions::const_iterator it = m_options->cbegin(); it != m_options->cend(); ++it) for(CaptureOptions::const_iterator it = m_options->cbegin(); it != m_options->cend(); ++it)
{ {
if (_stricmp(*it, "h264") == 0) m_frameType = FRAME_TYPE_H264; if (_stricmp(*it, "h264" ) == 0) m_frameType = FRAME_TYPE_H264;
if (_stricmp(*it, "nv12") == 0) m_frameType = FRAME_TYPE_NV12; if (_stricmp(*it, "yuv420") == 0) m_frameType = FRAME_TYPE_YUV420;
} }
if (m_frameType == FRAME_TYPE_H264) if (m_frameType == FRAME_TYPE_H264)
@ -162,9 +161,9 @@ bool DXGI::Initialize(CaptureOptions * options)
bool ok = false; bool ok = false;
switch (m_frameType) switch (m_frameType)
{ {
case FRAME_TYPE_ARGB: ok = InitRawCapture (); break; case FRAME_TYPE_ARGB : ok = InitRawCapture (); break;
case FRAME_TYPE_NV12: ok = InitNV12Capture(); break; case FRAME_TYPE_YUV420: ok = InitYUV420Capture(); break;
case FRAME_TYPE_H264: ok = InitH264Capture(); break; case FRAME_TYPE_H264 : ok = InitH264Capture (); break;
} }
if (!ok) if (!ok)
@ -221,7 +220,7 @@ bool DXGI::InitRawCapture()
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
texDesc.MiscFlags = 0; texDesc.MiscFlags = 0;
HRESULT status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture); HRESULT status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[0]);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to create texture", status); DEBUG_WINERROR("Failed to create texture", status);
@ -231,9 +230,11 @@ bool DXGI::InitRawCapture()
return true; return true;
} }
bool DXGI::InitNV12Capture() bool DXGI::InitYUV420Capture()
{ {
HRESULT status;
D3D11_TEXTURE2D_DESC texDesc; D3D11_TEXTURE2D_DESC texDesc;
ZeroMemory(&texDesc, sizeof(texDesc)); ZeroMemory(&texDesc, sizeof(texDesc));
texDesc.Width = m_width; texDesc.Width = m_width;
texDesc.Height = m_height; texDesc.Height = m_height;
@ -242,12 +243,29 @@ bool DXGI::InitNV12Capture()
texDesc.SampleDesc.Count = 1; texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0; texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_STAGING; texDesc.Usage = D3D11_USAGE_STAGING;
texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; texDesc.Format = DXGI_FORMAT_R8_UNORM;
texDesc.BindFlags = 0; texDesc.BindFlags = 0;
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
texDesc.MiscFlags = 0; texDesc.MiscFlags = 0;
HRESULT status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture); status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[0]);
if (FAILED(status))
{
DEBUG_WINERROR("Failed to create texture", status);
return false;
}
texDesc.Width /= 2;
texDesc.Height /= 2;
status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[1]);
if (FAILED(status))
{
DEBUG_WINERROR("Failed to create texture", status);
return false;
}
status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[2]);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to create texture", status); DEBUG_WINERROR("Failed to create texture", status);
@ -255,7 +273,7 @@ bool DXGI::InitNV12Capture()
} }
m_textureConverter = new TextureConverter(); m_textureConverter = new TextureConverter();
if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, DXGI_FORMAT_NV12)) if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, FRAME_TYPE_YUV420))
return false; return false;
return true; return true;
@ -264,7 +282,7 @@ bool DXGI::InitNV12Capture()
bool DXGI::InitH264Capture() bool DXGI::InitH264Capture()
{ {
m_textureConverter = new TextureConverter(); m_textureConverter = new TextureConverter();
if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, DXGI_FORMAT_NV12)) if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, FRAME_TYPE_YUV420))
return false; return false;
m_h264 = new MFT::H264(); m_h264 = new MFT::H264();
@ -297,13 +315,9 @@ void DXGI::DeInitialize()
m_pointerBufSize = 0; m_pointerBufSize = 0;
} }
if (m_surfaceMapped) SafeRelease(&m_texture[0]);
{ SafeRelease(&m_texture[1]);
m_deviceContext->Unmap(m_texture, 0); SafeRelease(&m_texture[2]);
m_surfaceMapped = false;
}
SafeRelease(&m_texture);
SafeRelease(&m_dup); SafeRelease(&m_dup);
SafeRelease(&m_output); SafeRelease(&m_output);
SafeRelease(&m_deviceContext); SafeRelease(&m_deviceContext);
@ -493,54 +507,10 @@ GrabStatus Capture::DXGI::ReleaseFrame()
GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cursor) GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cursor)
{ {
GrabStatus result; GrabStatus result;
ID3D11Texture2DPtr src; ID3D11Texture2DPtr texture;
bool timeout; bool timeout;
D3D11_MAPPED_SUBRESOURCE mapping;
result = GrabFrameTexture(frame, cursor, src, timeout);
if (timeout)
return GRAB_STATUS_TIMEOUT;
if (result != GRAB_STATUS_OK)
return result;
if (m_surfaceMapped)
{
m_deviceContext->Unmap(m_texture, 0);
m_surfaceMapped = false;
}
m_deviceContext->CopyResource(m_texture, src);
SafeRelease(&src);
result = ReleaseFrame();
if (result != GRAB_STATUS_OK)
return result;
HRESULT status;
status = m_deviceContext->Map(m_texture, 0, D3D11_MAP_READ, 0, &m_mapping);
if (FAILED(status))
{
DEBUG_WINERROR("Failed to map the texture", status);
DeInitialize();
return GRAB_STATUS_ERROR;
}
m_surfaceMapped = true;
frame.pitch = m_mapping.RowPitch;
frame.stride = m_mapping.RowPitch >> 2;
const unsigned int size = m_height * m_mapping.RowPitch;
memcpySSE(frame.buffer, m_mapping.pData, LG_MIN(size, frame.bufferSize));
return GRAB_STATUS_OK;
}
GrabStatus Capture::DXGI::GrabFrameNV12(struct FrameInfo & frame, struct CursorInfo & cursor)
{
GrabStatus result;
ID3D11Texture2DPtr texture;
bool timeout;
result = GrabFrameTexture(frame, cursor, texture, timeout); result = GrabFrameTexture(frame, cursor, texture, timeout);
if (timeout) if (timeout)
@ -549,19 +519,7 @@ GrabStatus Capture::DXGI::GrabFrameNV12(struct FrameInfo & frame, struct CursorI
if (result != GRAB_STATUS_OK) if (result != GRAB_STATUS_OK)
return result; return result;
if (!m_textureConverter->Convert(texture)) m_deviceContext->CopyResource(m_texture[0], texture);
{
SafeRelease(&texture);
return GRAB_STATUS_ERROR;
}
if (m_surfaceMapped)
{
m_deviceContext->Unmap(m_texture, 0);
m_surfaceMapped = false;
}
m_deviceContext->CopyResource(m_texture, texture);
SafeRelease(&texture); SafeRelease(&texture);
result = ReleaseFrame(); result = ReleaseFrame();
@ -569,26 +527,94 @@ GrabStatus Capture::DXGI::GrabFrameNV12(struct FrameInfo & frame, struct CursorI
return result; return result;
HRESULT status; HRESULT status;
status = m_deviceContext->Map(m_texture, 0, D3D11_MAP_READ, 0, &m_mapping); status = m_deviceContext->Map(m_texture[0], 0, D3D11_MAP_READ, 0, &mapping);
if (FAILED(status)) if (FAILED(status))
{ {
DEBUG_WINERROR("Failed to map the texture", status); DEBUG_WINERROR("Failed to map the texture", status);
DeInitialize(); DeInitialize();
return GRAB_STATUS_ERROR; return GRAB_STATUS_ERROR;
} }
m_surfaceMapped = true;
frame.pitch = m_mapping.RowPitch; frame.pitch = mapping.RowPitch;
frame.stride = m_mapping.RowPitch >> 2; frame.stride = mapping.RowPitch >> 2;
const unsigned int size = m_height * m_mapping.RowPitch; const unsigned int size = m_height * mapping.RowPitch;
memcpySSE(frame.buffer, m_mapping.pData, LG_MIN(size, frame.bufferSize)); memcpySSE(frame.buffer, mapping.pData, LG_MIN(size, frame.bufferSize));
m_deviceContext->Unmap(m_texture[0], 0);
return GRAB_STATUS_OK; return GRAB_STATUS_OK;
} }
GrabStatus Capture::DXGI::GrabFrameYUV420(struct FrameInfo & frame, struct CursorInfo & cursor)
{
GrabStatus result;
ID3D11Texture2DPtr texture;
bool timeout;
result = GrabFrameTexture(frame, cursor, texture, timeout);
if (timeout)
return GRAB_STATUS_TIMEOUT;
if (result != GRAB_STATUS_OK)
return result;
TextureList planes;
if (!m_textureConverter->Convert(texture, planes))
{
SafeRelease(&texture);
return GRAB_STATUS_ERROR;
}
SafeRelease(&texture);
for(int i = 0; i < 3; ++i)
{
ID3D11Texture2DPtr t = planes.at(i);
m_deviceContext->CopyResource(m_texture[i], planes.at(i));
SafeRelease(&t);
}
result = ReleaseFrame();
if (result != GRAB_STATUS_OK)
return result;
uint8_t * data = (uint8_t *)frame.buffer;
size_t remain = frame.bufferSize;
for(int i = 0; i < 3; ++i)
{
HRESULT status;
D3D11_MAPPED_SUBRESOURCE mapping;
status = m_deviceContext->Map(m_texture[i], 0, D3D11_MAP_READ, 0, &mapping);
if (FAILED(status))
{
DEBUG_WINERROR("Failed to map the texture", status);
DeInitialize();
return GRAB_STATUS_ERROR;
}
const unsigned int size = m_height * mapping.RowPitch;
if (size > remain)
{
m_deviceContext->Unmap(m_texture[i], 0);
DEBUG_ERROR("Too much data to fit in buffer");
return GRAB_STATUS_ERROR;
}
memcpySSE(data, mapping.pData, size);
data += size;
remain -= size;
m_deviceContext->Unmap(m_texture[i], 0);
}
frame.pitch = m_width;
frame.stride = m_width;
return GRAB_STATUS_OK;
}
GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorInfo & cursor) GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorInfo & cursor)
{ {
return GRAB_STATUS_ERROR;
#if 0
while(true) while(true)
{ {
unsigned int events = m_h264->Process(); unsigned int events = m_h264->Process();
@ -631,6 +657,7 @@ GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorI
return GRAB_STATUS_OK; return GRAB_STATUS_OK;
} }
} }
#endif
} }
GrabStatus DXGI::GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor) GrabStatus DXGI::GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor)
@ -640,8 +667,8 @@ GrabStatus DXGI::GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor)
switch (m_frameType) switch (m_frameType)
{ {
case FRAME_TYPE_NV12: return GrabFrameNV12(frame, cursor); case FRAME_TYPE_YUV420: return GrabFrameYUV420(frame, cursor);
case FRAME_TYPE_H264: return GrabFrameH264(frame, cursor); case FRAME_TYPE_H264 : return GrabFrameH264 (frame, cursor);
} }
return GrabFrameRaw(frame, cursor); return GrabFrameRaw(frame, cursor);

View file

@ -60,13 +60,13 @@ namespace Capture
private: private:
bool InitRawCapture(); bool InitRawCapture();
bool InitNV12Capture(); bool InitYUV420Capture();
bool InitH264Capture(); bool InitH264Capture();
GrabStatus GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout); GrabStatus GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout);
GrabStatus ReleaseFrame(); GrabStatus ReleaseFrame();
GrabStatus GrabFrameRaw (struct FrameInfo & frame, struct CursorInfo & cursor); GrabStatus GrabFrameRaw (struct FrameInfo & frame, struct CursorInfo & cursor);
GrabStatus GrabFrameNV12 (struct FrameInfo & frame, struct CursorInfo & cursor); GrabStatus GrabFrameYUV420 (struct FrameInfo & frame, struct CursorInfo & cursor);
GrabStatus GrabFrameH264 (struct FrameInfo & frame, struct CursorInfo & cursor); GrabStatus GrabFrameH264 (struct FrameInfo & frame, struct CursorInfo & cursor);
CaptureOptions * m_options; CaptureOptions * m_options;
@ -83,9 +83,7 @@ namespace Capture
IDXGIOutput1Ptr m_output; IDXGIOutput1Ptr m_output;
IDXGIOutputDuplicationPtr m_dup; IDXGIOutputDuplicationPtr m_dup;
bool m_releaseFrame; bool m_releaseFrame;
ID3D11Texture2DPtr m_texture; ID3D11Texture2DPtr m_texture[3];
D3D11_MAPPED_SUBRESOURCE m_mapping;
bool m_surfaceMapped;
TextureConverter * m_textureConverter; TextureConverter * m_textureConverter;
MFT::H264 * m_h264; MFT::H264 * m_h264;

View file

@ -1,26 +0,0 @@
Texture2D texTexture;
SamplerState texSampler;
struct VS
{
float4 pos : SV_Position;
float2 tex : TEXCOORD;
};
float4 RGBtoYUV(float4 rgba)
{
float4 yuva;
yuva.r = rgba.r * 0.2126 + 0.7152 * rgba.g + 0.0722 * rgba.b;
yuva.g = (rgba.b - yuva.r) / 1.8556;
yuva.b = (rgba.r - yuva.r) / 1.5748;
yuva.a = rgba.a;
yuva.gb += 0.5;
return yuva;
}
float4 main(VS input) : SV_TARGET
{
const float4 rgba = texTexture.Sample(texSampler, input.tex);
const float4 yuva = RGBtoYUV(rgba);
return yuva;
}

13
host/Shaders/Pixel.hlsl Normal file
View file

@ -0,0 +1,13 @@
Texture2D texTexture;
SamplerState texSampler;
struct VS
{
float4 pos : SV_Position;
float2 tex : TEXCOORD;
};
float4 main(VS input): SV_Target
{
return texTexture.Sample(texSampler, input.tex);
}

View file

@ -0,0 +1,31 @@
Texture2D texTexture;
SamplerState texSampler;
struct VS
{
float4 pos : SV_Position;
float2 tex : TEXCOORD;
};
struct OUT
{
float4 y: SV_TARGET0;
float4 u: SV_TARGET1;
float4 v: SV_TARGET2;
};
OUT main(VS input)
{
OUT o;
const float4 rgba = texTexture.Sample(texSampler, input.tex);
o.y.gba = 0.0f;
o.u.gba = 0.0f;
o.v.gba = 0.0f;
o.y.r = rgba.r * 0.2126 + 0.7152 * rgba.g + 0.0722 * rgba.b;
o.u.r = (rgba.b - o.y.r) / 1.8556;
o.v.r = (rgba.r - o.y.r) / 1.5748;
return o;
}

View file

@ -21,7 +21,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "common\debug.h" #include "common\debug.h"
#include "Shaders\Vertex.h" #include "Shaders\Vertex.h"
#include "Shaders\BGRAtoNV12.h" #include "Shaders\Pixel.h"
#include "Shaders\RGBtoYUV.h"
TextureConverter::TextureConverter() TextureConverter::TextureConverter()
{ {
@ -37,12 +38,12 @@ bool TextureConverter::Initialize(
ID3D11DevicePtr device, ID3D11DevicePtr device,
const unsigned int width, const unsigned int width,
const unsigned int height, const unsigned int height,
DXGI_FORMAT format FrameType format
) )
{ {
HRESULT result; HRESULT result;
D3D11_TEXTURE2D_DESC texDesc; D3D11_TEXTURE2D_DESC texDesc;
D3D11_RENDER_TARGET_VIEW_DESC viewDesc; D3D11_RENDER_TARGET_VIEW_DESC targetDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderDesc; D3D11_SHADER_RESOURCE_VIEW_DESC shaderDesc;
D3D11_SAMPLER_DESC samplerDesc; D3D11_SAMPLER_DESC samplerDesc;
@ -52,10 +53,21 @@ bool TextureConverter::Initialize(
m_height = height; m_height = height;
m_format = format; m_format = format;
result = device->CreatePixelShader(g_Pixel, sizeof(g_Pixel), NULL, &m_psCopy);
if (FAILED(result))
{
DeInitialize();
DEBUG_ERROR("Failed to create the copy pixel shader");
return false;
}
switch (format) switch (format)
{ {
case DXGI_FORMAT_NV12: case FRAME_TYPE_YUV420:
result = device->CreatePixelShader(g_BGRAtoNV12, sizeof(g_BGRAtoNV12), NULL, &m_pixelShader); result = device->CreatePixelShader(g_RGBtoYUV, sizeof(g_RGBtoYUV), NULL, &m_psConversion);
m_texFormats[0] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[0] = 1.0f;
m_texFormats[1] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[1] = 0.5f;
m_texFormats[2] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[2] = 0.5f;
break; break;
default: default:
@ -93,7 +105,7 @@ bool TextureConverter::Initialize(
} }
ZeroMemory(&texDesc , sizeof(texDesc )); ZeroMemory(&texDesc , sizeof(texDesc ));
ZeroMemory(&viewDesc , sizeof(viewDesc )); ZeroMemory(&targetDesc , sizeof(targetDesc ));
ZeroMemory(&shaderDesc , sizeof(shaderDesc )); ZeroMemory(&shaderDesc , sizeof(shaderDesc ));
ZeroMemory(&samplerDesc, sizeof(samplerDesc)); ZeroMemory(&samplerDesc, sizeof(samplerDesc));
@ -105,25 +117,45 @@ bool TextureConverter::Initialize(
texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.CPUAccessFlags = 0; texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0; texDesc.MiscFlags = 0;
texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
result = device->CreateTexture2D(&texDesc, NULL, &m_targetTexture);
if (FAILED(result))
{
DeInitialize();
DEBUG_ERROR("Failed to create the render texture");
return false;
}
viewDesc.Format = texDesc.Format; targetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
viewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
viewDesc.Texture2D.MipSlice = 0; shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
result = device->CreateRenderTargetView(m_targetTexture, &viewDesc, &m_renderView); shaderDesc.Texture2D.MipLevels = 1;
if (FAILED(result))
for(int i = 0; i < _countof(m_targetTexture); ++i)
{ {
DeInitialize(); if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN)
DEBUG_ERROR("Failed to create the render view"); continue;
return false;
texDesc .Format = m_texFormats[i];
targetDesc.Format = m_texFormats[i];
shaderDesc.Format = m_texFormats[i];
result = device->CreateTexture2D(&texDesc, NULL, &m_targetTexture[i]);
if (FAILED(result))
{
DeInitialize();
DEBUG_ERROR("Failed to create the render texture");
return false;
}
result = device->CreateRenderTargetView(m_targetTexture[i], &targetDesc, &m_renderView[i]);
if (FAILED(result))
{
DeInitialize();
DEBUG_ERROR("Failed to create the render view");
return false;
}
result = device->CreateShaderResourceView(m_targetTexture[i], &shaderDesc, &m_shaderView[i]);
if (FAILED(result))
{
DeInitialize();
DEBUG_ERROR("Failed to create the resource view");
return false;
}
} }
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
@ -242,14 +274,21 @@ void TextureConverter::DeInitialize()
SafeRelease(&m_samplerState ); SafeRelease(&m_samplerState );
SafeRelease(&m_indexBuffer ); SafeRelease(&m_indexBuffer );
SafeRelease(&m_vertexBuffer ); SafeRelease(&m_vertexBuffer );
SafeRelease(&m_renderView );
SafeRelease(&m_targetTexture); for(int i = 0; i < _countof(m_targetTexture); ++i)
SafeRelease(&m_vertexShader ); {
SafeRelease(&m_pixelShader ); SafeRelease(&m_shaderView [i]);
SafeRelease(&m_layout ); SafeRelease(&m_renderView [i]);
SafeRelease(&m_targetTexture[i]);
}
SafeRelease(&m_vertexShader);
SafeRelease(&m_psConversion);
SafeRelease(&m_layout );
SafeRelease(&m_psCopy );
} }
bool TextureConverter::Convert(ID3D11Texture2DPtr &texture) bool TextureConverter::Convert(ID3D11Texture2DPtr texture, TextureList & output)
{ {
unsigned int stride; unsigned int stride;
unsigned int offset; unsigned int offset;
@ -257,15 +296,15 @@ bool TextureConverter::Convert(ID3D11Texture2DPtr &texture)
HRESULT result; HRESULT result;
D3D11_TEXTURE2D_DESC texDesc; D3D11_TEXTURE2D_DESC texDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderDesc; D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
ID3D11ShaderResourceViewPtr textureView; ID3D11ShaderResourceViewPtr textureView;
texture->GetDesc(&texDesc); texture->GetDesc(&texDesc);
shaderDesc.Format = texDesc.Format; viewDesc.Format = texDesc.Format;
shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderDesc.Texture2D.MostDetailedMip = 0; viewDesc.Texture2D.MostDetailedMip = 0;
shaderDesc.Texture2D.MipLevels = 1; viewDesc.Texture2D.MipLevels = 1;
result = m_device->CreateShaderResourceView(texture, &shaderDesc, &textureView); result = m_device->CreateShaderResourceView(texture, &viewDesc, &textureView);
if (FAILED(result)) if (FAILED(result))
{ {
DeInitialize(); DeInitialize();
@ -273,19 +312,30 @@ bool TextureConverter::Convert(ID3D11Texture2DPtr &texture)
return false; return false;
} }
ID3D11Buffer *buffers [] = { m_vertexBuffer.GetInterfacePtr() }; ID3D11Buffer *buffers [] = { m_vertexBuffer.GetInterfacePtr() };
ID3D11RenderTargetView *renderViews [] = { m_renderView .GetInterfacePtr() };
ID3D11SamplerState *samplerStates[] = { m_samplerState.GetInterfacePtr() }; ID3D11SamplerState *samplerStates[] = { m_samplerState.GetInterfacePtr() };
ID3D11ShaderResourceView *shaderViews [] = { textureView .GetInterfacePtr() }; ID3D11ShaderResourceView *shaderViews [] = { textureView .GetInterfacePtr() };
D3D11_VIEWPORT viewPorts [] = { { D3D11_VIEWPORT viewPorts [] = { {
0.0f, 0.0f, 0.0f , 0.0f,
(float)m_width, (float)m_height, (float)m_width, (float)m_height,
0.0f, 1.0f 0.0f , 1.0f
} }; } };
m_deviceContext->OMSetRenderTargets(1, renderViews, NULL); int targetCount = 0;
m_deviceContext->ClearRenderTargetView(m_renderView, color); ID3D11RenderTargetView **renderViews = new ID3D11RenderTargetView*[_countof(m_renderView)];
for(int i = 0; i < _countof(m_renderView); ++i)
{
if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN)
continue;
m_deviceContext->ClearRenderTargetView(m_renderView[i], color);
renderViews[i] = m_renderView[i].GetInterfacePtr();
++targetCount;
}
m_deviceContext->PSSetShaderResources(0, _countof(shaderViews), shaderViews);
m_deviceContext->OMSetRenderTargets(targetCount, renderViews, NULL);
delete [] renderViews;
stride = sizeof(VS_INPUT); stride = sizeof(VS_INPUT);
offset = 0; offset = 0;
@ -296,14 +346,67 @@ bool TextureConverter::Convert(ID3D11Texture2DPtr &texture)
m_deviceContext->IASetIndexBuffer (m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); m_deviceContext->IASetIndexBuffer (m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
m_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); m_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
m_deviceContext->VSSetShader (m_vertexShader, NULL, 0); m_deviceContext->VSSetShader (m_vertexShader, NULL, 0);
m_deviceContext->PSSetSamplers (0, _countof(samplerStates), samplerStates); m_deviceContext->PSSetSamplers (0, _countof(samplerStates), samplerStates);
m_deviceContext->PSSetShaderResources (0, _countof(shaderViews ), shaderViews ); m_deviceContext->PSSetShader (m_psConversion, NULL, 0);
m_deviceContext->PSSetShader (m_pixelShader , NULL, 0);
m_deviceContext->DrawIndexed(m_indexCount, 0, 0); m_deviceContext->DrawIndexed(m_indexCount, 0, 0);
SafeRelease(&textureView); SafeRelease(&textureView);
SafeRelease(&texture);
texture = m_targetTexture; D3D11_RENDER_TARGET_VIEW_DESC targetDesc;
ZeroMemory(&targetDesc, sizeof(targetDesc));
targetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
m_deviceContext->PSSetShader(m_psCopy, NULL, 0);
renderViews = new ID3D11RenderTargetView*[1];
for (int i = 0; i < _countof(m_renderView); ++i)
{
if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN)
continue;
ID3D11Texture2DPtr src = m_targetTexture[i];
ID3D11Texture2DPtr dest;
ID3D11RenderTargetViewPtr view;
D3D11_TEXTURE2D_DESC srcDesc;
src->GetDesc(&srcDesc);
srcDesc.Width *= m_scaleFormats[i];
srcDesc.Height *= m_scaleFormats[i];
viewPorts[0].Width = srcDesc.Width;
viewPorts[0].Height = srcDesc.Height;
result = m_device->CreateTexture2D(&srcDesc, NULL, &dest);
if (FAILED(result))
{
delete[] renderViews;
DeInitialize();
DEBUG_ERROR("Failed to create the target texture");
return false;
}
targetDesc.Format = srcDesc.Format;
result = m_device->CreateRenderTargetView(dest, &targetDesc, &view);
if (FAILED(result))
{
SafeRelease(&dest);
delete[] renderViews;
DeInitialize();
DEBUG_ERROR("Failed to create the target view");
return false;
}
renderViews[0] = view.GetInterfacePtr();
shaderViews[0] = m_shaderView[i].GetInterfacePtr();
m_deviceContext->OMSetRenderTargets(1, renderViews, NULL);
m_deviceContext->RSSetViewports(_countof(viewPorts), viewPorts);
m_deviceContext->PSSetShaderResources(0, 1, shaderViews);
m_deviceContext->DrawIndexed(m_indexCount, 0, 0);
output.push_back(dest);
SafeRelease(&view);
}
delete[] renderViews;
return true; return true;
} }

View file

@ -20,8 +20,12 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#pragma once #pragma once
#include "Com.h" #include "Com.h"
#include "common\KVMFR.h"
#include <DirectXMath.h> #include <DirectXMath.h>
#include <vector>
typedef std::vector<ID3D11Texture2DPtr> TextureList;
class TextureConverter class TextureConverter
{ {
@ -34,12 +38,12 @@ public:
ID3D11DevicePtr device, ID3D11DevicePtr device,
const unsigned int width, const unsigned int width,
const unsigned int height, const unsigned int height,
DXGI_FORMAT format FrameType format
); );
void DeInitialize(); void DeInitialize();
bool Convert(ID3D11Texture2DPtr &texture); bool Convert(ID3D11Texture2DPtr texture, TextureList & output);
private: private:
struct VS_INPUT struct VS_INPUT
@ -53,13 +57,19 @@ private:
ID3D11DeviceContextPtr m_deviceContext; ID3D11DeviceContextPtr m_deviceContext;
ID3D11DevicePtr m_device; ID3D11DevicePtr m_device;
unsigned int m_width, m_height; unsigned int m_width, m_height;
DXGI_FORMAT m_format; FrameType m_format;
DXGI_FORMAT m_texFormats [3];
float m_scaleFormats [3];
ID3D11Texture2DPtr m_targetTexture[3];
ID3D11RenderTargetViewPtr m_renderView [3];
ID3D11ShaderResourceViewPtr m_shaderView [3];
ID3D11Texture2DPtr m_targetTexture;
ID3D11RenderTargetViewPtr m_renderView;
ID3D11InputLayoutPtr m_layout; ID3D11InputLayoutPtr m_layout;
ID3D11VertexShaderPtr m_vertexShader; ID3D11VertexShaderPtr m_vertexShader;
ID3D11PixelShaderPtr m_pixelShader; ID3D11PixelShaderPtr m_psCopy;
ID3D11PixelShaderPtr m_psConversion;
ID3D11SamplerStatePtr m_samplerState; ID3D11SamplerStatePtr m_samplerState;
ID3D11BufferPtr m_vertexBuffer; ID3D11BufferPtr m_vertexBuffer;

View file

@ -359,11 +359,16 @@
<MASM Include="..\common\memcpySSE.asm" /> <MASM Include="..\common\memcpySSE.asm" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<FxCompile Include="Shaders\BGRAtoNV12.hlsl"> <FxCompile Include="Shaders\Pixel.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_Pixel</VariableName>
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shaders\Pixel.h</HeaderFileOutput>
</FxCompile>
<FxCompile Include="Shaders\RGBtoYUV.hlsl">
<FileType>HLSL</FileType> <FileType>HLSL</FileType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType> <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_BGRAtoNV12</VariableName> <VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">g_RGBtoYUV</VariableName>
<HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shaders\BGRAtoNV12.h</HeaderFileOutput> <HeaderFileOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Shaders\RGBtoYUV.h</HeaderFileOutput>
</FxCompile> </FxCompile>
<FxCompile Include="Shaders\Vertex.hlsl"> <FxCompile Include="Shaders\Vertex.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType> <ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>

View file

@ -105,11 +105,12 @@
</MASM> </MASM>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<FxCompile Include="Shaders\BGRAtoNV12.hlsl">
<Filter>Source Files\Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\Vertex.hlsl"> <FxCompile Include="Shaders\Vertex.hlsl">
<Filter>Source Files\Shaders</Filter> <Filter>Source Files\Shaders</Filter>
</FxCompile> </FxCompile>
<FxCompile Include="Shaders\RGBtoYUV.hlsl">
<Filter>Source Files\Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\Pixel.hlsl" />
</ItemGroup> </ItemGroup>
</Project> </Project>