aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Fedchin <anightik@gmail.com>2017-04-26 12:44:04 +0300
committerAnton Fedchin <anightik@gmail.com>2017-07-17 11:43:31 +0300
commit6c6a46c2a95267ec9a525c817c9d8cec7b67b583 (patch)
tree6040a2e42c4c5bc1e4519a6bc05f48528114e552
parentc8e1ba473b52d3f0501707dd4ea51f0ba6d4c9c8 (diff)
[VideoPlayer] WinRenderer: rework to use new CWinRenderBuffer
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp327
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h46
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp118
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h23
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp660
-rw-r--r--xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h132
6 files changed, 385 insertions, 921 deletions
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp
index ccdc90a698..7abba569c5 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp
@@ -30,6 +30,7 @@
#include "DXVAHD.h"
#include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
#include "cores/VideoPlayer/VideoRenderers/RenderFlags.h"
+#include "cores/VideoPlayer/VideoRenderers/WinVideoBuffer.h"
#include "settings/MediaSettings.h"
#include "utils/Log.h"
#include "utils/win32/memcpy_sse2.h"
@@ -48,17 +49,14 @@ do { \
} while(0);
CProcessorHD::CProcessorHD()
+ : m_width(0)
+ , m_height(0)
+ , m_pVideoDevice(nullptr)
+ , m_pVideoContext(nullptr)
+ , m_pEnumerator(nullptr)
+ , m_pVideoProcessor(nullptr)
{
- m_pVideoDevice = nullptr;
- m_pVideoContext = nullptr;
- m_pEnumerator = nullptr;
- m_pVideoProcessor = nullptr;
- m_eViewType = PROCESSOR_VIEW_TYPE_UNKNOWN;
g_Windowing.Register(this);
-
- m_context = nullptr;
- m_width = 0;
- m_height = 0;
}
CProcessorHD::~CProcessorHD()
@@ -79,9 +77,7 @@ void CProcessorHD::Close()
CSingleLock lock(m_section);
SAFE_RELEASE(m_pEnumerator);
SAFE_RELEASE(m_pVideoProcessor);
- SAFE_RELEASE(m_context);
SAFE_RELEASE(m_pVideoContext);
- m_eViewType = PROCESSOR_VIEW_TYPE_UNKNOWN;
}
bool CProcessorHD::PreInit()
@@ -110,8 +106,6 @@ bool CProcessorHD::PreInit()
return false;
}
- memset(&m_texDesc, 0, sizeof(D3D11_TEXTURE2D_DESC));
-
SAFE_RELEASE(m_pEnumerator);
return true;
}
@@ -182,8 +176,8 @@ bool CProcessorHD::InitProcessor()
CLog::Log(LOGDEBUG, "%s: Selected video processor index: %d.", __FUNCTION__, m_procIndex);
LOGIFERROR(m_pEnumerator->GetVideoProcessorRateConversionCaps(m_procIndex, &m_rateCaps))
- m_max_fwd_refs = m_rateCaps.FutureFrames;
- m_max_back_refs = m_rateCaps.PastFrames;
+ m_max_fwd_refs = std::min(m_rateCaps.FutureFrames, 2u);
+ m_max_back_refs = std::min(m_rateCaps.PastFrames, 4u);
CLog::Log(LOGNOTICE, "%s: Supported deinterlace methods: Blend:%s, Bob:%s, Adaptive:%s, MoComp:%s.", __FUNCTION__,
(m_rateCaps.ProcessorCaps & 0x1) != 0 ? "yes" : "no", // BLEND
@@ -194,7 +188,7 @@ bool CProcessorHD::InitProcessor()
CLog::Log(LOGDEBUG, "%s: Selected video processor allows %d future frames and %d past frames.", __FUNCTION__, m_rateCaps.FutureFrames, m_rateCaps.PastFrames);
- m_size = m_max_back_refs + 1 + m_max_fwd_refs + 3; // refs + 1 display + 3 safety frames
+ m_size = m_max_back_refs + 1 + m_max_fwd_refs; // refs + 1 display
// Get the image filtering capabilities.
for (long i = 0; i < NUM_FILTERS; i++)
@@ -222,7 +216,7 @@ bool CProcessorHD::InitProcessor()
return true;
}
-bool DXVA::CProcessorHD::IsFormatSupported(DXGI_FORMAT format, D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT support) const
+bool CProcessorHD::IsFormatSupported(DXGI_FORMAT format, D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT support) const
{
UINT uiFlags;
if (S_OK == m_pEnumerator->CheckVideoProcessorFormat(format, &uiFlags))
@@ -235,40 +229,15 @@ bool DXVA::CProcessorHD::IsFormatSupported(DXGI_FORMAT format, D3D11_VIDEO_PROCE
return false;
}
-bool CProcessorHD::ConfigureProcessor(AVPixelFormat format, DXGI_FORMAT dxva_format)
+bool CProcessorHD::CheckFormats() const
{
// check default output format DXGI_FORMAT_B8G8R8A8_UNORM (as render target)
if (!IsFormatSupported(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT))
return false;
-
- if (format == AV_PIX_FMT_D3D11VA_VLD)
- {
- m_textureFormat = dxva_format;
- m_eViewType = PROCESSOR_VIEW_TYPE_DECODER;
- }
- else
- {
- m_textureFormat = DXGI_FORMAT_NV12; // default
-
- if (format == AV_PIX_FMT_YUV420P)
- m_textureFormat = DXGI_FORMAT_NV12;
- if (format == AV_PIX_FMT_YUV420P10)
- m_textureFormat = DXGI_FORMAT_P010;
- if (format == AV_PIX_FMT_YUV420P16)
- m_textureFormat = DXGI_FORMAT_P016;
-
- m_eViewType = PROCESSOR_VIEW_TYPE_PROCESSOR;
- }
-
- if (!IsFormatSupported(m_textureFormat, D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT))
- return false;
- if (m_eViewType == PROCESSOR_VIEW_TYPE_PROCESSOR && !CreateSurfaces())
- return false;
-
return true;
}
-bool CProcessorHD::Open(UINT width, UINT height, unsigned int flags, AVPixelFormat format, DXGI_FORMAT dxva_format)
+bool CProcessorHD::Open(UINT width, UINT height)
{
Close();
@@ -276,13 +245,11 @@ bool CProcessorHD::Open(UINT width, UINT height, unsigned int flags, AVPixelForm
m_width = width;
m_height = height;
- m_flags = flags;
- m_renderFormat = format;
if (!InitProcessor())
return false;
- if (!ConfigureProcessor(m_renderFormat, dxva_format))
+ if (!CheckFormats())
return false;
return OpenProcessor();
@@ -299,7 +266,7 @@ bool CProcessorHD::ReInit()
if (!InitProcessor())
return false;
- if (!ConfigureProcessor(m_renderFormat, m_textureFormat))
+ if (!CheckFormats())
return false;
return true;
@@ -314,7 +281,7 @@ bool CProcessorHD::OpenProcessor()
return false;
SAFE_RELEASE(m_pVideoProcessor);
- CLog::Log(LOGDEBUG, "%s: Creating processor with input format: (%d).", __FUNCTION__, m_textureFormat);
+ CLog::Log(LOGDEBUG, "%s: Creating processor.", __FUNCTION__);
// create processor
HRESULT hr = m_pVideoDevice->CreateVideoProcessor(m_pEnumerator, m_procIndex, &m_pVideoProcessor);
@@ -324,18 +291,6 @@ bool CProcessorHD::OpenProcessor()
return false;
}
- D3D11_VIDEO_PROCESSOR_COLOR_SPACE cs
- {
- 0, // 0 - Playback, 1 - Processing
- 0, // 0 - Full (0-255), 1 - Limited (16-235)
- m_flags & CONF_FLAGS_YUVCOEF_BT709 ? 1 : 0, // 0 - BT.601, 1 - BT.709
- 0, // 0 - Conventional YCbCr, 1 - xvYCC
- m_flags & CONF_FLAGS_YUV_FULLRANGE ? 2 : 1, // 2 - Full luminance range [0-255], 1 - Studio luminance range [16-235], 0 - driver defaults
- };
- if (m_vcaps.DeviceCaps & D3D11_VIDEO_PROCESSOR_DEVICE_CAPS_NOMINAL_RANGE)
- cs.Nominal_Range = m_flags & CONF_FLAGS_YUV_FULLRANGE ? 2 : 1;
- m_pVideoContext->VideoProcessorSetStreamColorSpace(m_pVideoProcessor, DEFAULT_STREAM_INDEX, &cs);
-
// Output background color (black)
D3D11_VIDEO_COLOR color;
color.YCbCr = { 0.0625f, 0.5f, 0.5f, 1.0f }; // black color
@@ -344,124 +299,6 @@ bool CProcessorHD::OpenProcessor()
return true;
}
-bool CProcessorHD::CreateSurfaces()
-{
- HRESULT hr;
- size_t idx;
- ID3D11Device* pD3DDevice = g_Windowing.Get3D11Device();
-
- // we cannot use texture array (like in decoder) for USAGE_DYNAMIC, so create separate textures
- CD3D11_TEXTURE2D_DESC texDesc(m_textureFormat, FFALIGN(m_width, 16), FFALIGN(m_height, 16), 1, 1, D3D11_BIND_DECODER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
- D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC pivd = { 0, D3D11_VPIV_DIMENSION_TEXTURE2D };
- pivd.Texture2D.ArraySlice = 0;
- pivd.Texture2D.MipSlice = 0;
-
- ID3D11VideoProcessorInputView* views[32] = { nullptr };
- CLog::Log(LOGDEBUG, "%s - Creating %d processor surfaces with format %d.", __FUNCTION__, m_size, m_textureFormat);
-
- for (idx = 0; idx < m_size; idx++)
- {
- ID3D11Texture2D* pTexture = nullptr;
- hr = pD3DDevice->CreateTexture2D(&texDesc, nullptr, &pTexture);
- if (FAILED(hr))
- break;
-
- hr = m_pVideoDevice->CreateVideoProcessorInputView(pTexture, m_pEnumerator, &pivd, &views[idx]);
- SAFE_RELEASE(pTexture);
- if (FAILED(hr))
- break;
- }
-
- if (idx != m_size)
- {
- // something goes wrong
- CLog::Log(LOGERROR, "%s: Failed to create processor surfaces.", __FUNCTION__);
- for (idx = 0; idx < m_size; idx++)
- {
- SAFE_RELEASE(views[idx]);
- }
- return false;
- }
-
- m_context = new CSurfaceContext();
- for (unsigned int i = 0; i < m_size; i++)
- {
- m_context->AddSurface(views[i]);
- }
-
- m_texDesc = texDesc;
- return true;
-}
-
-CRenderPicture *CProcessorHD::Convert(const VideoPicture &picture) const
-{
- if (!picture.videoBuffer)
- return nullptr;
-
- AVPixelFormat format = picture.videoBuffer->GetFormat();
- if ( format != AV_PIX_FMT_YUV420P
- && format != AV_PIX_FMT_YUV420P10
- && format != AV_PIX_FMT_YUV420P16
- && format != AV_PIX_FMT_D3D11VA_VLD)
- {
- CLog::Log(LOGERROR, "%s: colorspace not supported by processor, skipping frame.", __FUNCTION__);
- return nullptr;
- }
-
- if (format == AV_PIX_FMT_D3D11VA_VLD)
- {
- CDXVAVideoBuffer* pic = dynamic_cast<CDXVAVideoBuffer*>(picture.videoBuffer);
- return pic->picture->Acquire();
- }
-
- ID3D11View *pView = m_context->GetFree(nullptr);
- if (!pView)
- {
- CLog::Log(LOGERROR, "%s: no free video surface", __FUNCTION__);
- return nullptr;
- }
-
- ID3D11Resource* pResource = nullptr;
- pView->GetResource(&pResource);
-
- D3D11_MAPPED_SUBRESOURCE rectangle;
- ID3D11DeviceContext* pContext = g_Windowing.GetImmediateContext();
-
- if (FAILED(pContext->Map(pResource, 0, D3D11_MAP_WRITE_DISCARD, 0, &rectangle)))
- {
- CLog::Log(LOGERROR, "%s: could not lock rect", __FUNCTION__);
- m_context->ClearReference(pView);
- return nullptr;
- }
-
- uint8_t* planes[3]; picture.videoBuffer->GetPlanes(planes);
- int strides[3]; picture.videoBuffer->GetStrides(strides);
-
- uint8_t* pData = static_cast<uint8_t*>(rectangle.pData);
- uint8_t* dst[] = { pData, pData + m_texDesc.Height * rectangle.RowPitch };
- int dstStride[] = { rectangle.RowPitch, rectangle.RowPitch };
-
- if (format == AV_PIX_FMT_YUV420P)
- {
- convert_yuv420_nv12(planes, strides, picture.iHeight, picture.iWidth, dst, dstStride);
- }
- else if(format == AV_PIX_FMT_YUV420P10
- || format == AV_PIX_FMT_YUV420P16)
- {
- convert_yuv420_p01x(planes, strides, picture.iHeight, picture.iWidth, dst, dstStride
- , format == AV_PIX_FMT_YUV420P10 ? 10 : 16);
- }
- pContext->Unmap(pResource, 0);
- SAFE_RELEASE(pResource);
-
- m_context->ClearReference(pView);
- m_context->MarkRender(pView);
-
- CRenderPicture *pic = new CRenderPicture(m_context);
- pic->view = pView;
- return pic;
-}
-
bool CProcessorHD::ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER filter, int value, int min, int max, int def) const
{
if (filter >= NUM_FILTERS)
@@ -485,21 +322,18 @@ bool CProcessorHD::ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER filter, int value, i
return true;
}
-ID3D11VideoProcessorInputView* CProcessorHD::GetInputView(ID3D11View* view) const
+ID3D11VideoProcessorInputView* CProcessorHD::GetInputView(SWinVideoBuffer* view) const
{
ID3D11VideoProcessorInputView* inputView = nullptr;
- if (m_eViewType == PROCESSOR_VIEW_TYPE_PROCESSOR)
- {
- inputView = reinterpret_cast<ID3D11VideoProcessorInputView*>(view);
- inputView->AddRef(); // it will be released later
- }
- else if (m_eViewType == PROCESSOR_VIEW_TYPE_DECODER)
+ D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC vpivd = { 0, D3D11_VPIV_DIMENSION_TEXTURE2D,{ 0, 0 } };
+
+ if (view->format == BUFFER_FMT_DXVA_BYPASS)
{
// the view cames from decoder
- ID3D11VideoDecoderOutputView* decoderView = reinterpret_cast<ID3D11VideoDecoderOutputView*>(view);
+ ID3D11VideoDecoderOutputView* decoderView = reinterpret_cast<ID3D11VideoDecoderOutputView*>(view->GetHWView());
if (!decoderView)
{
- CLog::Log(LOGERROR, "%s: cannot get view.", __FUNCTION__);
+ CLog::Log(LOGERROR, "%s: cannot get decoder view.", __FUNCTION__);
return nullptr;
}
@@ -507,22 +341,39 @@ ID3D11VideoProcessorInputView* CProcessorHD::GetInputView(ID3D11View* view) cons
D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC vdovd;
decoderView->GetDesc(&vdovd);
decoderView->GetResource(&resource);
-
- D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC vpivd;
- vpivd.FourCC = 0;
- vpivd.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
vpivd.Texture2D.ArraySlice = vdovd.Texture2D.ArraySlice;
- vpivd.Texture2D.MipSlice = 0;
if (FAILED(m_pVideoDevice->CreateVideoProcessorInputView(resource, m_pEnumerator, &vpivd, &inputView)))
- CLog::Log(LOGERROR, "%s: cannot create processor view.", __FUNCTION__);
+ CLog::Log(LOGERROR, "%s: cannot create processor input view.", __FUNCTION__);
resource->Release();
}
+ else if (view->format == BUFFER_FMT_DXVA_NV12
+ || view->format == BUFFER_FMT_DXVA_P010
+ || view->format == BUFFER_FMT_DXVA_P016)
+ {
+ if (FAILED(m_pVideoDevice->CreateVideoProcessorInputView(view->GetResource(), m_pEnumerator, &vpivd, &inputView)))
+ CLog::Log(LOGERROR, "%s: cannot create processor input view.", __FUNCTION__);
+ }
+
return inputView;
}
-bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11View** views, DWORD flags, UINT frameIdx, UINT rotation)
+static void ReleaseStream(D3D11_VIDEO_PROCESSOR_STREAM &stream_data)
+{
+ SAFE_RELEASE(stream_data.pInputSurface);
+
+ for (size_t i = 0; i < stream_data.PastFrames; ++i)
+ SAFE_RELEASE(stream_data.ppPastSurfaces[i]);
+
+ for (size_t i = 0; i < stream_data.FutureFrames; ++i)
+ SAFE_RELEASE(stream_data.ppFutureSurfaces[i]);
+
+ delete[] stream_data.ppPastSurfaces;
+ delete[] stream_data.ppFutureSurfaces;
+}
+
+bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, SWinVideoBuffer** views, DWORD flags, UINT frameIdx, UINT rotation)
{
HRESULT hr;
CSingleLock lock(m_section);
@@ -558,43 +409,51 @@ bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11Vi
stream_data.Enable = TRUE;
stream_data.PastFrames = pastFrames;
stream_data.FutureFrames = futureFrames;
- stream_data.ppPastSurfaces = new ID3D11VideoProcessorInputView*[pastFrames];
- stream_data.ppFutureSurfaces = new ID3D11VideoProcessorInputView*[futureFrames];
- stream_data.pInputSurfaceRight = nullptr;
- stream_data.ppPastSurfacesRight = nullptr;
- stream_data.ppFutureSurfacesRight = nullptr;
+ if (pastFrames)
+ stream_data.ppPastSurfaces = new ID3D11VideoProcessorInputView*[pastFrames];
+ if (futureFrames)
+ stream_data.ppFutureSurfaces = new ID3D11VideoProcessorInputView*[futureFrames];
+ ID3D11VideoProcessorInputView* view = nullptr;
int start = 2 - futureFrames;
int end = 2 + pastFrames;
-
- D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC pivd;
- ZeroMemory(&pivd, sizeof(D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC));
- pivd.FourCC = 0;
- pivd.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
- pivd.Texture2D.ArraySlice = 0;
- pivd.Texture2D.MipSlice = 0;
+ int count = 0;
for (int i = start; i <= end; i++)
{
if (!views[i])
continue;
+ view = GetInputView(views[i]);
if (i > 2)
{
// frames order should be { ?, T-3, T-2, T-1 }
- stream_data.ppPastSurfaces[2 + pastFrames - i] = GetInputView(views[i]);
+ stream_data.ppPastSurfaces[2 + pastFrames - i] = view;
}
else if (i == 2)
{
- stream_data.pInputSurface = GetInputView(views[2]);
+ stream_data.pInputSurface = view;
}
else if (i < 2)
{
// frames order should be { T+1, T+2, T+3, .. }
- stream_data.ppFutureSurfaces[1 - i] = GetInputView(views[i]);
+ stream_data.ppFutureSurfaces[1 - i] = view;
}
+ if (view)
+ count++;
}
+ if (count != pastFrames + futureFrames + 1)
+ {
+ CLog::Log(LOGERROR, "%s: incomplete views set.", __FUNCTION__);
+ ReleaseStream(stream_data);
+ return false;
+ }
+
+ // fix locked textures
+ for (int i = start; i <= end; i++)
+ if (i != 2 && views[i]) views[i]->StartRender();
+
if (flags & RENDER_FLAG_FIELD0 && flags & RENDER_FLAG_TOP)
dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST;
else if (flags & RENDER_FLAG_FIELD1 && flags & RENDER_FLAG_BOT)
@@ -612,6 +471,16 @@ bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11Vi
// input format
m_pVideoContext->VideoProcessorSetStreamFrameFormat(m_pVideoProcessor, DEFAULT_STREAM_INDEX, dxvaFrameFormat);
+ // input colorspace
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace
+ {
+ 0, // 0 - Playback, 1 - Processing
+ 0, // 0 - Full (0-255), 1 - Limited (16-235) (RGB)
+ views[2]->flags & CONF_FLAGS_YUVCOEF_BT709 ? 1 : 0, // 0 - BT.601, 1 - BT.709
+ 0, // 0 - Conventional YCbCr, 1 - xvYCC
+ views[2]->flags & CONF_FLAGS_YUV_FULLRANGE ? 2 : 1, // 0 - driver defaults, 2 - Full range [0-255], 1 - Studio range [16-235] (YUV)
+ };
+ m_pVideoContext->VideoProcessorSetStreamColorSpace(m_pVideoProcessor, DEFAULT_STREAM_INDEX, &colorSpace);
// Source rect
m_pVideoContext->VideoProcessorSetStreamSourceRect(m_pVideoProcessor, DEFAULT_STREAM_INDEX, TRUE, &sourceRECT);
// Stream dest rect
@@ -620,39 +489,30 @@ bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11Vi
m_pVideoContext->VideoProcessorSetOutputTargetRect(m_pVideoProcessor, TRUE, &dstRECT);
// Output color space
// don't apply any color range conversion, this will be fixed at later stage.
- D3D11_VIDEO_PROCESSOR_COLOR_SPACE colorSpace = {};
colorSpace.Usage = 0; // 0 - playback, 1 - video processing
colorSpace.RGB_Range = g_Windowing.UseLimitedColor() ? 1 : 0; // 0 - 0-255, 1 - 16-235
colorSpace.YCbCr_Matrix = 1; // 0 - BT.601, 1 = BT.709
colorSpace.YCbCr_xvYCC = 1; // 0 - Conventional YCbCr, 1 - xvYCC
colorSpace.Nominal_Range = 0; // 2 - 0-255, 1 = 16-235, 0 - undefined
-
m_pVideoContext->VideoProcessorSetOutputColorSpace(m_pVideoProcessor, &colorSpace);
-
+ // brightness
ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_BRIGHTNESS,
CMediaSettings::GetInstance().GetCurrentVideoSettings().m_Brightness, 0, 100, 50);
+ // contrast
ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_CONTRAST,
CMediaSettings::GetInstance().GetCurrentVideoSettings().m_Contrast, 0, 100, 50);
+ // unused filters
ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_HUE, 50, 0, 100, 50);
ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER_SATURATION, 50, 0, 100, 50);
// Rotation
- m_pVideoContext->VideoProcessorSetStreamRotation(m_pVideoProcessor, DEFAULT_STREAM_INDEX, (rotation != 0), (D3D11_VIDEO_PROCESSOR_ROTATION)(rotation / 90));
-
- //
- // Create Output View of Output Surfaces.
- //
- D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc;
- ZeroMemory(&OutputViewDesc, sizeof(OutputViewDesc));
- OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
- OutputViewDesc.Texture2D.MipSlice = 0;
- OutputViewDesc.Texture2DArray.ArraySize = 0; // 2 for stereo
- OutputViewDesc.Texture2DArray.MipSlice = 0;
- OutputViewDesc.Texture2DArray.FirstArraySlice = 0;
-
- ID3D11VideoProcessorOutputView* pOutputView;
+ m_pVideoContext->VideoProcessorSetStreamRotation(m_pVideoProcessor, DEFAULT_STREAM_INDEX, rotation != 0
+ , static_cast<D3D11_VIDEO_PROCESSOR_ROTATION>(rotation / 90));
+ // create output view for surface.
+ D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc = { D3D11_VPOV_DIMENSION_TEXTURE2D, { 0 }};
+ ID3D11VideoProcessorOutputView* pOutputView = nullptr;
hr = m_pVideoDevice->CreateVideoProcessorOutputView(target, m_pEnumerator, &OutputViewDesc, &pOutputView);
if (S_OK != hr)
- CLog::Log(FAILED(hr) ? LOGERROR : LOGWARNING, "%s: Device returns result '%x' while creating processor output.", __FUNCTION__, hr);
+ CLog::Log(FAILED(hr) ? LOGERROR : LOGWARNING, "%s: Device returns result '%x' while creating processor output view.", __FUNCTION__, hr);
if (SUCCEEDED(hr))
{
@@ -664,16 +524,7 @@ bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11Vi
}
SAFE_RELEASE(pOutputView);
- SAFE_RELEASE(stream_data.pInputSurface);
-
- for (size_t i = 0; i < stream_data.PastFrames; ++i)
- SAFE_RELEASE(stream_data.ppPastSurfaces[i]);
-
- for (size_t i = 0; i < stream_data.FutureFrames; ++i)
- SAFE_RELEASE(stream_data.ppFutureSurfaces[i]);
-
- delete[] stream_data.ppPastSurfaces;
- delete[] stream_data.ppFutureSurfaces;
+ ReleaseStream(stream_data);
return !FAILED(hr);
}
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h
index 031722d516..cb62fb77e1 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h
@@ -25,6 +25,8 @@
#include "guilib/D3DResource.h"
#include "guilib/Geometry.h"
+class SWinVideoBuffer;
+
namespace DXVA {
// ProcAmp filters d3d11 filters
@@ -36,13 +38,6 @@ const D3D11_VIDEO_PROCESSOR_FILTER PROCAMP_FILTERS[] =
D3D11_VIDEO_PROCESSOR_FILTER_SATURATION
};
-enum PROCESSOR_VIEW_TYPE
-{
- PROCESSOR_VIEW_TYPE_UNKNOWN = 0,
- PROCESSOR_VIEW_TYPE_DECODER = 1,
- PROCESSOR_VIEW_TYPE_PROCESSOR = 2
-};
-
const DWORD NUM_FILTERS = ARRAYSIZE(PROCAMP_FILTERS);
class CProcessorHD : public ID3DResource
@@ -53,11 +48,10 @@ public:
bool PreInit();
void UnInit();
- bool Open(UINT width, UINT height, unsigned int flags, AVPixelFormat format, DXGI_FORMAT dxva_format);
+ bool Open(UINT width, UINT height);
void Close();
- CRenderPicture *Convert(const VideoPicture &picture) const;
- bool Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11View **views, DWORD flags, UINT frameIdx, UINT rotation);
- uint8_t Size() const { if (m_pVideoProcessor) return m_size; return 0; }
+ bool Render(CRect src, CRect dst, ID3D11Resource* target, SWinVideoBuffer **views, DWORD flags, UINT frameIdx, UINT rotation);
+ uint8_t Size() const { return m_pVideoProcessor ? m_size : 0; }
uint8_t PastRefs() const { return m_max_back_refs; }
// ID3DResource overrides
@@ -69,41 +63,33 @@ public:
protected:
bool ReInit();
bool InitProcessor();
- bool ConfigureProcessor(AVPixelFormat format, DXGI_FORMAT dxva_format);
+ bool CheckFormats() const;
bool OpenProcessor();
- bool CreateSurfaces();
bool ApplyFilter(D3D11_VIDEO_PROCESSOR_FILTER filter, int value, int min, int max, int def) const;
- ID3D11VideoProcessorInputView* GetInputView(ID3D11View* view) const;
+ ID3D11VideoProcessorInputView* GetInputView(SWinVideoBuffer* view) const;
bool IsFormatSupported(DXGI_FORMAT format, D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT support) const;
+ CCriticalSection m_section;
+
uint32_t m_width;
uint32_t m_height;
- uint32_t m_flags = 0;
- AVPixelFormat m_renderFormat = AV_PIX_FMT_NONE;
- uint8_t m_size = 0;
- uint8_t m_max_back_refs = 0;
- uint8_t m_max_fwd_refs = 0;
+ uint8_t m_size;
+ uint8_t m_max_back_refs;
+ uint8_t m_max_fwd_refs;
+ uint32_t m_procIndex;
+ D3D11_VIDEO_PROCESSOR_CAPS m_vcaps;
+ D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS m_rateCaps;
struct ProcAmpInfo
{
bool bSupported;
- D3D11_VIDEO_PROCESSOR_FILTER_RANGE Range;
+ D3D11_VIDEO_PROCESSOR_FILTER_RANGE Range;
};
ProcAmpInfo m_Filters[NUM_FILTERS];
-
- DXGI_FORMAT m_textureFormat;
ID3D11VideoDevice *m_pVideoDevice;
ID3D11VideoContext *m_pVideoContext;
ID3D11VideoProcessorEnumerator *m_pEnumerator;
- D3D11_VIDEO_PROCESSOR_CAPS m_vcaps;
ID3D11VideoProcessor *m_pVideoProcessor;
- CSurfaceContext *m_context;
- CCriticalSection m_section;
-
- uint32_t m_procIndex = 0;
- D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS m_rateCaps;
- D3D11_TEXTURE2D_DESC m_texDesc;
- PROCESSOR_VIEW_TYPE m_eViewType;
};
};
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
index 18d7685b76..e9063be2a2 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
@@ -42,10 +42,10 @@ CYUV2RGBMatrix::CYUV2RGBMatrix()
m_contrast = 0.0f;
m_flags = 0;
m_limitedRange = false;
- m_format = SHADER_NONE;
+ m_format = BUFFER_FMT_NONE;
}
-void CYUV2RGBMatrix::SetParameters(float contrast, float blacklevel, unsigned int flags, EShaderFormat format)
+void CYUV2RGBMatrix::SetParameters(float contrast, float blacklevel, unsigned int flags, EBufferFormat format)
{
if (m_contrast != contrast)
{
@@ -79,7 +79,10 @@ XMFLOAT4X4* CYUV2RGBMatrix::Matrix()
if (m_NeedRecalc)
{
TransformMatrix matrix;
- CalculateYUVMatrix(matrix, m_flags, m_format, m_blacklevel, m_contrast, m_limitedRange);
+ EShaderFormat fmt = SHADER_NONE;
+ if (m_format == BUFFER_FMT_YUV420P10 || m_format == BUFFER_FMT_DXVA_P010)
+ fmt = SHADER_YV12_10;
+ CalculateYUVMatrix(matrix, m_flags, fmt, m_blacklevel, m_contrast, m_limitedRange);
m_mat._11 = matrix.m[0][0];
m_mat._12 = matrix.m[1][0];
@@ -480,41 +483,35 @@ void COutputShader::CreateDitherView()
//==================================================================================
-bool CYUV2RGBShader::Create(unsigned int sourceWidth, unsigned int sourceHeight, EShaderFormat fmt, COutputShader *pCLUT)
+bool CYUV2RGBShader::Create(EBufferFormat fmt, COutputShader *pCLUT)
{
- CWinShader::CreateVertexBuffer(4, sizeof(CUSTOMVERTEX));
-
- m_sourceWidth = sourceWidth;
- m_sourceHeight = sourceHeight;
m_format = fmt;
m_pOutShader = pCLUT;
- unsigned int texWidth;
-
DefinesMap defines;
switch (fmt)
{
- case SHADER_YV12:
- case SHADER_YV12_10:
- case SHADER_YV12_16:
+ case BUFFER_FMT_YUV420P:
+ case BUFFER_FMT_YUV420P10:
+ case BUFFER_FMT_YUV420P16:
defines["XBMC_YV12"] = "";
- texWidth = sourceWidth;
break;
- case SHADER_NV12:
+ case BUFFER_FMT_DXVA_BYPASS:
+ case BUFFER_FMT_DXVA_NV12:
+ case BUFFER_FMT_DXVA_P010:
+ case BUFFER_FMT_DXVA_P016:
+ case BUFFER_FMT_NV12:
defines["XBMC_NV12"] = "";
- texWidth = sourceWidth;
// FL 9.x doesn't support DXGI_FORMAT_R8G8_UNORM, so we have to use SNORM and correct values in shader
if (!g_Windowing.IsFormatSupport(DXGI_FORMAT_R8G8_UNORM, D3D11_FORMAT_SUPPORT_TEXTURE2D))
defines["NV12_SNORM_UV"] = "";
break;
- case SHADER_UYVY:
+ case BUFFER_FMT_UYVY422:
defines["XBMC_UYVY"] = "";
- texWidth = sourceWidth >> 1;
break;
- case SHADER_YUY2:
+ case BUFFER_FMT_YUYV422:
defines["XBMC_YUY2"] = "";
- texWidth = sourceWidth >> 1;
break;
default:
return false;
@@ -523,9 +520,6 @@ bool CYUV2RGBShader::Create(unsigned int sourceWidth, unsigned int sourceHeight,
if (m_pOutShader)
m_pOutShader->GetDefines(defines);
- m_texSteps[0] = 1.0f/(float)texWidth;
- m_texSteps[1] = 1.0f/(float)sourceHeight;
-
std::string effectString = "special://xbmc/system/shaders/yuv2rgb_d3d.fx";
if(!LoadEffect(effectString, &defines))
@@ -534,6 +528,7 @@ bool CYUV2RGBShader::Create(unsigned int sourceWidth, unsigned int sourceHeight,
return false;
}
+ CWinShader::CreateVertexBuffer(4, sizeof(CUSTOMVERTEX));
// Create input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
@@ -550,22 +545,17 @@ bool CYUV2RGBShader::Create(unsigned int sourceWidth, unsigned int sourceHeight,
return true;
}
-void CYUV2RGBShader::Render(CRect sourceRect, CPoint dest[],
- float contrast,
- float brightness,
- unsigned int flags,
- YUVBuffer* YUVbuf)
+void CYUV2RGBShader::Render(CRect sourceRect, CPoint dest[], float contrast, float brightness, SWinVideoBuffer* videoBuffer)
{
- PrepareParameters(sourceRect, dest,
- contrast, brightness, flags);
- SetShaderParameters(YUVbuf);
+ PrepareParameters(videoBuffer, sourceRect, dest, contrast, brightness);
+ SetShaderParameters(videoBuffer);
Execute(nullptr, 4);
}
-CYUV2RGBShader::CYUV2RGBShader() :
- m_sourceWidth(0)
+CYUV2RGBShader::CYUV2RGBShader()
+ : m_sourceWidth(0)
, m_sourceHeight(0)
- , m_format(RENDER_FMT_NONE)
+ , m_format(BUFFER_FMT_NONE)
, m_pOutShader(nullptr)
{
memset(&m_texSteps, 0, sizeof(m_texSteps));
@@ -575,19 +565,20 @@ CYUV2RGBShader::~CYUV2RGBShader()
{
}
-void CYUV2RGBShader::PrepareParameters(CRect sourceRect,
- CPoint dest[],
- float contrast,
- float brightness,
- unsigned int flags)
+void CYUV2RGBShader::PrepareParameters(SWinVideoBuffer* videoBuffer, CRect sourceRect, CPoint dest[],
+ float contrast, float brightness)
{
- if (m_sourceRect != sourceRect
+ if (m_sourceRect != sourceRect
|| m_dest[0] != dest[0] || m_dest[1] != dest[1]
- || m_dest[2] != dest[2] || m_dest[3] != dest[3])
+ || m_dest[2] != dest[2] || m_dest[3] != dest[3]
+ || videoBuffer->GetWidth() != m_sourceWidth
+ || videoBuffer->GetHeight() != m_sourceHeight)
{
m_sourceRect = sourceRect;
for (size_t i = 0; i < 4; ++i)
m_dest[i] = dest[i];
+ m_sourceWidth = videoBuffer->GetWidth();
+ m_sourceHeight = videoBuffer->GetHeight();
CUSTOMVERTEX* v;
CWinShader::LockVertexBuffer(reinterpret_cast<void**>(&v));
@@ -627,23 +618,30 @@ void CYUV2RGBShader::PrepareParameters(CRect sourceRect,
CWinShader::UnlockVertexBuffer();
}
+ unsigned int texWidth = m_sourceWidth;
+ if ( m_format == BUFFER_FMT_UYVY422
+ || m_format == BUFFER_FMT_YUYV422)
+ texWidth = texWidth >> 1;
+
+ m_texSteps[0] = 1.0f / texWidth;
+ m_texSteps[1] = 1.0f / m_sourceHeight;
+
m_matrix.SetParameters(contrast * 0.02f,
brightness * 0.01f - 0.5f,
- flags,
+ videoBuffer->flags,
m_format);
}
-void CYUV2RGBShader::SetShaderParameters(YUVBuffer* YUVbuf)
+void CYUV2RGBShader::SetShaderParameters(SWinVideoBuffer* videoBuffer)
{
m_effect.SetTechnique("YUV2RGB_T");
- SVideoPlane *planes = YUVbuf->planes;
ID3D11ShaderResourceView* ppSRView[3] =
{
- planes[0].texture.GetShaderResource(),
- planes[1].texture.GetShaderResource(),
- planes[2].texture.GetShaderResource(),
+ reinterpret_cast<ID3D11ShaderResourceView*>(videoBuffer->GetView(0)),
+ reinterpret_cast<ID3D11ShaderResourceView*>(videoBuffer->GetView(1)),
+ reinterpret_cast<ID3D11ShaderResourceView*>(videoBuffer->GetView(2)),
};
- m_effect.SetResources("g_Texture", ppSRView, YUVbuf->GetActivePlanes());
+ m_effect.SetResources("g_Texture", ppSRView, videoBuffer->GetActivePlanes());
m_effect.SetMatrix("g_ColorMatrix", m_matrix.Matrix());
m_effect.SetFloatArray("g_StepXY", m_texSteps, ARRAY_SIZE(m_texSteps));
@@ -789,11 +787,9 @@ bool CConvolutionShader1Pass::Create(ESCALINGMETHOD method, COutputShader *pCLUT
}
void CConvolutionShader1Pass::Render(CD3DTexture &sourceTexture,
- unsigned int sourceWidth, unsigned int sourceHeight,
- unsigned int destWidth, unsigned int destHeight,
- CRect sourceRect,
- CRect destRect,
- bool useLimitRange)
+ unsigned int sourceWidth, unsigned int sourceHeight,
+ unsigned int destWidth, unsigned int destHeight,
+ CRect sourceRect, CRect destRect, bool useLimitRange)
{
PrepareParameters(sourceWidth, sourceHeight, sourceRect, destRect);
float texSteps[] = { 1.0f/(float)sourceWidth, 1.0f/(float)sourceHeight};
@@ -855,8 +851,8 @@ void CConvolutionShader1Pass::SetShaderParameters(CD3DTexture &sourceTexture, fl
m_effect.SetFloatArray("g_viewPort", &viewPort.Width, 2);
float colorRange[2] =
{
- (useLimitRange ? 16.f : 0.f) / 255.f,
- (useLimitRange ? (235.f - 16.f) : 255.f) / 255.f,
+ (useLimitRange ? 16.f / 255.f : 0.f),
+ (useLimitRange ? 219.f / 255.f : 1.f),
};
m_effect.SetFloatArray("g_colorRange", colorRange, _countof(colorRange));
if (m_pOutShader)
@@ -938,11 +934,9 @@ bool CConvolutionShaderSeparable::Create(ESCALINGMETHOD method, COutputShader *p
}
void CConvolutionShaderSeparable::Render(CD3DTexture &sourceTexture,
- unsigned int sourceWidth, unsigned int sourceHeight,
- unsigned int destWidth, unsigned int destHeight,
- CRect sourceRect,
- CRect destRect,
- bool useLimitRange)
+ unsigned int sourceWidth, unsigned int sourceHeight,
+ unsigned int destWidth, unsigned int destHeight,
+ CRect sourceRect, CRect destRect, bool useLimitRange)
{
if(m_destWidth != destWidth || m_sourceHeight != sourceHeight)
CreateIntermediateRenderTarget(destWidth, sourceHeight);
@@ -1105,8 +1099,8 @@ void CConvolutionShaderSeparable::SetShaderParameters(CD3DTexture &sourceTexture
m_effect.SetFloatArray("g_StepXY", texSteps, texStepsCount);
float colorRange[2] =
{
- (useLimitRange ? 16.f : 0.f) / 255.f,
- (useLimitRange ? (235.f - 16.f) : 255.f) / 255.f,
+ (useLimitRange ? 16.f / 255.f : 0.f),
+ (useLimitRange ? 219.f / 255.f : 1.f)
};
m_effect.SetFloatArray("g_colorRange", colorRange, _countof(colorRange));
if (m_pOutShader)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h
index 770cfdcd5d..be3c6a8754 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.h
@@ -20,7 +20,6 @@
*
*/
-#ifdef HAS_DX
#include <vector>
#include "../../guilib/Geometry.h"
@@ -34,7 +33,7 @@ class CYUV2RGBMatrix
{
public:
CYUV2RGBMatrix();
- void SetParameters(float contrast, float blacklevel, unsigned int flags, EShaderFormat format);
+ void SetParameters(float contrast, float blacklevel, unsigned int flags, EBufferFormat format);
XMFLOAT4X4* Matrix();
private:
@@ -43,7 +42,7 @@ private:
float m_blacklevel;
unsigned int m_flags;
bool m_limitedRange;
- EShaderFormat m_format;
+ EBufferFormat m_format;
XMFLOAT4X4 m_mat;
};
@@ -120,26 +119,22 @@ private:
class CYUV2RGBShader : public CWinShader
{
public:
- virtual bool Create(unsigned int sourceWidth, unsigned int sourceHeight, EShaderFormat fmt, COutputShader *pOutShader = nullptr);
- virtual void Render(CRect sourceRect, CPoint dest[], float contrast, float brightness,
- unsigned int flags, YUVBuffer* YUVbuf);
CYUV2RGBShader();
virtual ~CYUV2RGBShader();
+ virtual bool Create(EBufferFormat fmt, COutputShader *pOutShader = nullptr);
+ virtual void Render(CRect sourceRect, CPoint dest[], float contrast, float brightness, SWinVideoBuffer* videoBuffer);
protected:
- virtual void PrepareParameters(CRect sourceRect,
- CPoint dest[],
- float contrast,
- float brightness,
- unsigned int flags);
- virtual void SetShaderParameters(YUVBuffer* YUVbuf);
+ void PrepareParameters(SWinVideoBuffer* videoBuffer, CRect sourceRect, CPoint dest[],
+ float contrast, float brightness);
+ void SetShaderParameters(SWinVideoBuffer* videoBuffer);
private:
CYUV2RGBMatrix m_matrix;
unsigned int m_sourceWidth, m_sourceHeight;
CRect m_sourceRect;
CPoint m_dest[4];
- EShaderFormat m_format;
+ EBufferFormat m_format;
float m_texSteps[2];
COutputShader *m_pOutShader;
@@ -236,5 +231,3 @@ class CTestShader : public CWinShader
public:
virtual bool Create();
};
-
-#endif
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
index 1c5f8f3e1e..4664d65857 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
@@ -47,7 +47,7 @@ static RenderMethodDetail RenderMethodDetails[] = {
{ RENDER_SW , "Software" },
{ RENDER_PS , "Pixel Shaders" },
{ RENDER_DXVA , "DXVA" },
- { RENDER_INVALID, NULL }
+ { RENDER_INVALID, nullptr }
};
static RenderMethodDetail *FindRenderMethod(RenderMethod m)
@@ -71,6 +71,8 @@ bool CWinRenderer::Register()
}
CWinRenderer::CWinRenderer()
+ : m_frameIdx(0)
+ , m_bufferFormat(BUFFER_FMT_NONE)
{
m_iYV12RenderBuffer = 0;
m_NumYV12Buffers = 0;
@@ -83,12 +85,12 @@ CWinRenderer::CWinRenderer()
m_renderMethod = RENDER_PS;
m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
- m_scalingMethodGui = (ESCALINGMETHOD)-1;
+ m_scalingMethodGui = static_cast<ESCALINGMETHOD>(-1);
m_bUseHQScaler = false;
m_bFilterInitialized = false;
- for (int i = 0; i<NUM_BUFFERS; i++)
+ for (int i = 0; i < NUM_BUFFERS; i++)
m_VideoBuffers[i] = nullptr;
m_sw_scale_ctx = nullptr;
@@ -132,70 +134,91 @@ void CWinRenderer::ManageTextures()
void CWinRenderer::SelectRenderMethod()
{
- // Set rendering to dxva before trying it, in order to open the correct processor immediately, when deinterlacing method is auto.
+ EBufferFormat dxFormat = SelectBufferFormat(m_format, RENDER_DXVA);
+ EBufferFormat psFormat = SelectBufferFormat(m_format, RENDER_PS);
+ // modern drivers allow using HW pic in shaders
+ bool allowChangeMethod = dxFormat == psFormat;
- // Force dxva renderer after dxva decoding: PS and SW renderers have performance issues after dxva decode.
- if (g_advancedSettings.m_DXVAForceProcessorRenderer && m_format == AV_PIX_FMT_D3D11VA_VLD)
+ // old drivers + HW decoded picture -> we must force DXVA render method
+ if (!allowChangeMethod && m_format == AV_PIX_FMT_D3D11VA_VLD)
{
- CLog::Log(LOGNOTICE, "D3D: rendering method forced to DXVA processor");
+ CLog::Log(LOGNOTICE, "%s: rendering method forced to DXVA processor.", __FUNCTION__);
m_renderMethod = RENDER_DXVA;
- if (!m_processor || !m_processor->Open(m_sourceWidth, m_sourceHeight, m_iFlags, m_format, m_dxva_format))
+ if (!m_processor || !m_processor->Open(m_sourceWidth, m_sourceHeight))
{
- CLog::Log(LOGNOTICE, "D3D: unable to open DXVA processor");
- if (m_processor)
+ CLog::Log(LOGNOTICE, "%s: unable to open DXVA processor.", __FUNCTION__);
+ if (m_processor)
m_processor->Close();
m_renderMethod = RENDER_INVALID;
}
}
else
{
- CLog::Log(LOGDEBUG, __FUNCTION__": Requested render method: %d", m_iRequestedMethod);
-
- switch(m_iRequestedMethod)
+ CLog::Log(LOGDEBUG, "%s: requested render method: %d", __FUNCTION__, m_iRequestedMethod);
+ switch (m_iRequestedMethod)
{
- case RENDER_METHOD_DXVA:
- if (!m_processor || !m_processor->Open(m_sourceWidth, m_sourceHeight, m_iFlags, m_format, m_dxva_format))
- {
- CLog::Log(LOGNOTICE, "D3D: unable to open DXVA processor");
- if (m_processor)
- m_processor->Close();
- }
- else
+ case RENDER_METHOD_DXVA:
+ {
+ // skip if format isn't DXVA compatible.
+ if (dxFormat >= BUFFER_FMT_DXVA_BYPASS)
+ {
+ if (m_processor && m_processor->Open(m_sourceWidth, m_sourceHeight))
{
m_renderMethod = RENDER_DXVA;
break;
}
- // Drop through to pixel shader
- case RENDER_METHOD_AUTO:
- case RENDER_METHOD_D3D_PS:
+ allowChangeMethod = false;
+ CLog::Log(LOGNOTICE, "%s: unable to open DXVA processor.", __FUNCTION__);
+ if (m_processor)
+ m_processor->Close();
+ }
+ }
+ // fallback to auto
+ case RENDER_METHOD_AUTO:
+ if (allowChangeMethod)
+ {
+ // for modern drivers select method depends on input
+ // for HW decoded or interlaced picture prefer DXVA method.
+ if (m_format == RENDER_FMT_DXVA || m_iFlags & DVP_FLAG_INTERLACED)
{
- CTestShader shader;
- if (shader.Create())
+ if (m_processor && m_processor->Open(m_sourceWidth, m_sourceHeight))
{
- m_renderMethod = RENDER_PS;
- if (m_format == AV_PIX_FMT_D3D11VA_VLD)
- m_format = AV_PIX_FMT_NV12;
+ m_renderMethod = RENDER_DXVA;
break;
}
- else
- {
- CLog::Log(LOGNOTICE, "D3D: unable to load test shader - D3D installation is most likely incomplete");
- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, "DirectX", g_localizeStrings.Get(2101));
- }
- CLog::Log(LOGNOTICE, "D3D: falling back to SW mode");
+ CLog::Log(LOGNOTICE, "%s: unable to open DXVA processor", __FUNCTION__);
+ if (m_processor)
+ m_processor->Close();
}
- // drop through to software
- case RENDER_METHOD_SOFTWARE:
- default:
- // So we'll do the color conversion in software.
- m_renderMethod = RENDER_SW;
+ }
+ // drop through to pixel shader
+ case RENDER_METHOD_D3D_PS:
+ {
+ CTestShader shader;
+ if (shader.Create())
+ {
+ m_renderMethod = RENDER_PS;
break;
+ }
+ // this is something out of the ordinary
+ CLog::Log(LOGNOTICE, "%s: unable to load test shader - D3D installation is most likely incomplete, falling back to SW mode.", __FUNCTION__);
+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, "DirectX", g_localizeStrings.Get(2101));
+ }
+ // drop through to software
+ case RENDER_METHOD_SOFTWARE:
+ default:
+ // so we'll do the color conversion in software.
+ m_renderMethod = RENDER_SW;
+ break;
}
}
- RenderMethodDetail *rmdet = FindRenderMethod(m_renderMethod);
- CLog::Log(LOGDEBUG, __FUNCTION__": Selected render method %d: %s", m_renderMethod, rmdet != nullptr ? rmdet->name : "unknown");
+ m_bufferFormat = SelectBufferFormat(m_format, m_renderMethod);
m_frameIdx = 0;
+
+ RenderMethodDetail *rmdet = FindRenderMethod(m_renderMethod);
+ CLog::Log(LOGDEBUG, "%s: selected render method %d: %s", __FUNCTION__, m_renderMethod, rmdet != nullptr ? rmdet->name : "unknown");
+ CLog::Log(LOGDEBUG, "%s: selected buffer format %d", __FUNCTION__, m_bufferFormat);
}
bool CWinRenderer::Configure(const VideoPicture &picture, float fps, unsigned flags, unsigned int orientation)
@@ -232,12 +255,11 @@ bool CWinRenderer::Configure(const VideoPicture &picture, float fps, unsigned fl
return true;
}
-int CWinRenderer::NextYV12Texture()
+int CWinRenderer::NextYV12Texture() const
{
if(m_NumYV12Buffers)
return (m_iYV12RenderBuffer + 1) % m_NumYV12Buffers;
- else
- return -1;
+ return -1;
}
void CWinRenderer::AddVideoPicture(const VideoPicture &picture, int index, double currentClock)
@@ -246,23 +268,10 @@ void CWinRenderer::AddVideoPicture(const VideoPicture &picture, int index, doubl
if (!m_VideoBuffers[index])
return;
- if (m_renderMethod == RENDER_DXVA)
- {
- DXVABuffer *buf = reinterpret_cast<DXVABuffer*>(m_VideoBuffers[index]);
- SAFE_RELEASE(buf->pic);
- buf->pic = m_processor->Convert(picture);
- buf->frameIdx = m_frameIdx;
- buf->pictureFlags = picture.iFlags;
- m_frameIdx += 2;
- }
- else
- {
- YUVBuffer *buf = reinterpret_cast<YUVBuffer*>(m_VideoBuffers[index]);
- if (buf->IsReadyToRender())
- return;
-
- buf->CopyFromPicture(picture);
- }
+ m_VideoBuffers[index]->ReleaseHWPicture();
+ m_VideoBuffers[index]->ApplyPicture(picture);
+ m_VideoBuffers[index]->frameIdx = m_frameIdx;
+ m_frameIdx += 2;
m_VideoBuffers[index]->videoBuffer = picture.videoBuffer;
m_VideoBuffers[index]->videoBuffer->Acquire();
}
@@ -305,8 +314,6 @@ void CWinRenderer::FlipPage(int source)
if (m_iYV12RenderBuffer >= 0 && m_VideoBuffers[m_iYV12RenderBuffer] != nullptr)
m_VideoBuffers[m_iYV12RenderBuffer]->StartRender();
-
- return;
}
void CWinRenderer::PreInit()
@@ -317,15 +324,11 @@ void CWinRenderer::PreInit()
m_iRequestedMethod = CServiceBroker::GetSettings().GetInt(CSettings::SETTING_VIDEOPLAYER_RENDERMETHOD);
- if (g_advancedSettings.m_DXVAForceProcessorRenderer
- || m_iRequestedMethod == RENDER_METHOD_DXVA)
+ m_processor = new DXVA::CProcessorHD();
+ if (!m_processor->PreInit())
{
- m_processor = new DXVA::CProcessorHD();
- if (!m_processor->PreInit())
- {
- CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA processor - skipping");
- SAFE_DELETE(m_processor);
- }
+ CLog::Log(LOGNOTICE, "%: - could not init DXVA processor - skipping.", __FUNCTION__);
+ SAFE_DELETE(m_processor);
}
}
@@ -394,16 +397,77 @@ bool CWinRenderer::CreateIntermediateRenderTarget(unsigned int width, unsigned i
if (m_IntermediateTarget.Get())
m_IntermediateTarget.Release();
- CLog::Log(LOGDEBUG, __FUNCTION__": format %i", format);
+ CLog::Log(LOGDEBUG, "%s: format %i.", __FUNCTION__, format);
if (!m_IntermediateTarget.Create(width, height, 1, dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT, format))
{
- CLog::Log(LOGERROR, __FUNCTION__": intermediate render target creation failed.");
+ CLog::Log(LOGERROR, "%s: intermediate render target creation failed.", __FUNCTION__);
return false;
}
return true;
}
+EBufferFormat CWinRenderer::SelectBufferFormat(const ERenderFormat format, const RenderMethod method) const
+{
+ EBufferFormat buffer_format = BUFFER_FMT_NONE;
+ if (m_format == RENDER_FMT_DXVA) buffer_format = BUFFER_FMT_YUV420P;
+ if (m_format == RENDER_FMT_NV12) buffer_format = BUFFER_FMT_YUV420P;
+ if (m_format == RENDER_FMT_YUV420P) buffer_format = BUFFER_FMT_YUV420P;
+ if (m_format == RENDER_FMT_YUV420P10) buffer_format = BUFFER_FMT_YUV420P10;
+ if (m_format == RENDER_FMT_YUV420P16) buffer_format = BUFFER_FMT_YUV420P16;
+ // is they still used?
+ if (m_format == RENDER_FMT_YUYV422) buffer_format = BUFFER_FMT_YUYV422;
+ if (m_format == RENDER_FMT_UYVY422) buffer_format = BUFFER_FMT_UYVY422;
+
+ if (method == RENDER_SW)
+ return buffer_format;
+
+ ID3D11Device* pDevice = g_Windowing.Get3D11Device();
+ CD3D11_TEXTURE2D_DESC texDesc(DXGI_FORMAT_UNKNOWN,
+ m_sourceWidth, m_sourceHeight, 1, 1,
+ D3D11_BIND_SHADER_RESOURCE,
+ D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
+ if (method == RENDER_DXVA)
+ texDesc.BindFlags |= D3D11_BIND_DECODER;
+
+ switch (format)
+ {
+ case RENDER_FMT_NV12:
+ case RENDER_FMT_YUV420P:
+ case RENDER_FMT_YUV420P10:
+ case RENDER_FMT_YUV420P16:
+ {
+ texDesc.Format = DXGI_FORMAT_NV12;
+ if (m_format == RENDER_FMT_YUV420P10) texDesc.Format = DXGI_FORMAT_P010;
+ if (m_format == RENDER_FMT_YUV420P16) texDesc.Format = DXGI_FORMAT_P016;
+
+ if (SUCCEEDED(pDevice->CreateTexture2D(&texDesc, nullptr, nullptr)))
+ {
+ buffer_format = BUFFER_FMT_DXVA_NV12;
+ if (m_format == RENDER_FMT_YUV420P10) buffer_format = BUFFER_FMT_DXVA_P010;
+ if (m_format == RENDER_FMT_YUV420P16) buffer_format = BUFFER_FMT_DXVA_P016;
+ }
+ return buffer_format;
+ }
+ case RENDER_FMT_DXVA:
+ {
+ texDesc.Format = m_dxva_format;
+ texDesc.Usage = D3D11_USAGE_DEFAULT;
+ texDesc.CPUAccessFlags = 0;
+
+ if (method == RENDER_DXVA || SUCCEEDED(pDevice->CreateTexture2D(&texDesc, nullptr, nullptr)))
+ return BUFFER_FMT_DXVA_BYPASS;
+
+ if (m_dxva_format == DXGI_FORMAT_P010)
+ return BUFFER_FMT_YUV420P10;
+ if (m_dxva_format == DXGI_FORMAT_P016)
+ return BUFFER_FMT_YUV420P16;
+ }
+ default:
+ return buffer_format;
+ }
+}
+
void CWinRenderer::SelectSWVideoFilter()
{
CreateIntermediateRenderTarget(m_sourceWidth, m_sourceHeight, true);
@@ -449,7 +513,8 @@ void CWinRenderer::SelectPSVideoFilter()
if (m_scalingMethod == VS_SCALINGMETHOD_AUTO)
{
bool scaleSD = m_sourceHeight < 720 && m_sourceWidth < 1280;
- bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() && (int)m_sourceWidth < g_graphicsContext.GetWidth();
+ bool scaleUp = static_cast<int>(m_sourceHeight) < g_graphicsContext.GetHeight()
+ && static_cast<int>(m_sourceWidth) < g_graphicsContext.GetWidth();
bool scaleFps = m_fps < (g_advancedSettings.m_videoAutoScaleMaxFps + 0.01f);
if (m_renderMethod == RENDER_DXVA)
@@ -479,7 +544,7 @@ void CWinRenderer::UpdatePSVideoFilter()
if (!m_scalerShader->Create(m_scalingMethod, m_outputShader))
{
SAFE_DELETE(m_scalerShader);
- CLog::Log(LOGNOTICE, __FUNCTION__": two pass convolution shader init problem, falling back to one pass.");
+ CLog::Log(LOGNOTICE, "%s: two pass convolution shader init problem, falling back to one pass.", __FUNCTION__);
}
// Fallback on the one pass version
@@ -514,8 +579,7 @@ void CWinRenderer::UpdatePSVideoFilter()
}
m_colorShader = new CYUV2RGBShader();
- EShaderFormat shaderFormat = GetShaderFormat();
- if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, shaderFormat, m_bUseHQScaler ? nullptr : m_outputShader))
+ if (!m_colorShader->Create(m_bufferFormat, m_bUseHQScaler ? nullptr : m_outputShader))
{
if (m_bUseHQScaler)
{
@@ -541,11 +605,8 @@ void CWinRenderer::UpdateVideoFilter()
bool cmsChanged = m_cmsOn != m_colorManager->IsEnabled()
|| m_cmsOn && !m_colorManager->CheckConfiguration(m_cmsToken, m_iFlags);
if (m_scalingMethodGui == CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod
- && m_bFilterInitialized
- && !cmsChanged)
- {
+ && m_bFilterInitialized && !cmsChanged)
return;
- }
m_bFilterInitialized = true;
m_scalingMethodGui = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod;
@@ -553,14 +614,12 @@ void CWinRenderer::UpdateVideoFilter()
if (!Supports(m_scalingMethod))
{
- CLog::Log(LOGWARNING, __FUNCTION__" - chosen scaling method %d is not supported by renderer", (int)m_scalingMethod);
+ CLog::Log(LOGWARNING, "%s: chosen scaling method %d is not supported by renderer", __FUNCTION__, static_cast<int>(m_scalingMethod));
m_scalingMethod = VS_SCALINGMETHOD_AUTO;
}
if (cmsChanged)
- {
ColorManagmentUpdate();
- }
if (cmsChanged || !m_outputShader)
{
@@ -643,26 +702,17 @@ void CWinRenderer::RenderSW()
m_sourceWidth, m_sourceHeight, AV_PIX_FMT_BGRA,
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
- YUVBuffer* buf = reinterpret_cast<YUVBuffer*>(m_VideoBuffers[m_iYV12RenderBuffer]);
+ SWinVideoBuffer* buf = m_VideoBuffers[m_iYV12RenderBuffer];
- D3D11_MAPPED_SUBRESOURCE srclr[3];
- uint8_t* src[3];
- int srcStride[3];
+ uint8_t* src[MAX_PLANES];
+ int srcStride[MAX_PLANES];
for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
- {
- if(!(buf->planes[idx].texture.LockRect(0, &srclr[idx], D3D11_MAP_READ)))
- CLog::Log(LOGERROR, __FUNCTION__" - failed to lock yuv textures into memory");
- else
- {
- src[idx] = (uint8_t*)srclr[idx].pData;
- srcStride[idx] = srclr[idx].RowPitch;
- }
- }
+ buf->MapPlane(idx, reinterpret_cast<void**>(&src[idx]), &srcStride[idx]);
D3D11_MAPPED_SUBRESOURCE destlr;
if (!m_IntermediateTarget.LockRect(0, &destlr, D3D11_MAP_WRITE_DISCARD))
- CLog::Log(LOGERROR, __FUNCTION__" - failed to lock swtarget texture into memory");
+ CLog::Log(LOGERROR, "%s: failed to lock swtarget texture into memory.", __FUNCTION__);
uint8_t *dst[] = { static_cast<uint8_t*>(destlr.pData), nullptr, nullptr };
int dstStride[] = { static_cast<int>(destlr.RowPitch), 0, 0 };
@@ -670,11 +720,10 @@ void CWinRenderer::RenderSW()
sws_scale(m_sw_scale_ctx, src, srcStride, 0, m_sourceHeight, dst, dstStride);
for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
- if(!(buf->planes[idx].texture.UnlockRect(0)))
- CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock yuv textures");
+ buf->UnmapPlane(idx);
if (!m_IntermediateTarget.UnlockRect(0))
- CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock swtarget texture");
+ CLog::Log(LOGERROR, "%s: failed to unlock swtarget texture.", __FUNCTION__);
// 2. output to display
@@ -685,7 +734,7 @@ void CWinRenderer::RenderSW()
void CWinRenderer::RenderPS()
{
- CD3D11_VIEWPORT viewPort(0.0f, 0.0f, 0.0f, 0.0f);
+ CD3D11_VIEWPORT viewPort;
ID3D11DeviceContext* pContext = g_Windowing.Get3D11Context();
ID3D11RenderTargetView *oldRTView = nullptr; ID3D11DepthStencilView* oldDSView = nullptr;
@@ -730,7 +779,7 @@ void CWinRenderer::RenderPS()
m_colorShader->Render(m_sourceRect, destPoints,
CMediaSettings::GetInstance().GetCurrentVideoSettings().m_Contrast,
CMediaSettings::GetInstance().GetCurrentVideoSettings().m_Brightness,
- m_iFlags, reinterpret_cast<YUVBuffer*>(m_VideoBuffers[m_iYV12RenderBuffer]));
+ m_VideoBuffers[m_iYV12RenderBuffer]);
// Restore our view port.
g_Windowing.RestoreViewPort();
// Restore the render target and depth view.
@@ -751,17 +800,22 @@ void CWinRenderer::RenderHQ()
void CWinRenderer::RenderHW(DWORD flags)
{
- DXVABuffer *image = reinterpret_cast<DXVABuffer*>(m_VideoBuffers[m_iYV12RenderBuffer]);
- if (!image->pic)
+ SWinVideoBuffer *image = m_VideoBuffers[m_iYV12RenderBuffer];
+ if (image->format != BUFFER_FMT_DXVA_BYPASS
+ && image->format != BUFFER_FMT_DXVA_NV12
+ && image->format != BUFFER_FMT_DXVA_P010
+ && image->format != BUFFER_FMT_DXVA_P016)
return;
+ if (!image->HasPic())
+ return;
+
int past = 0;
int future = 0;
- DXVABuffer **buffers = reinterpret_cast<DXVABuffer**>(m_VideoBuffers);
- ID3D11View* views[8];
- memset(views, 0, 8 * sizeof(ID3D11View*));
- views[2] = image->pic->view;
+ SWinVideoBuffer* views[8];
+ memset(views, 0, 8 * sizeof(SWinVideoBuffer*));
+ views[2] = image;
// set future frames
while (future < 2)
@@ -769,9 +823,10 @@ void CWinRenderer::RenderHW(DWORD flags)
bool found = false;
for (int i = 0; i < m_NumYV12Buffers; i++)
{
- if (buffers[i] && buffers[i]->pic && buffers[i]->frameIdx == image->frameIdx + (future*2 + 2))
+ if (m_VideoBuffers[i] && m_VideoBuffers[i]->HasPic()
+ && m_VideoBuffers[i]->frameIdx == image->frameIdx + (future*2 + 2))
{
- views[1 - future++] = buffers[i]->pic->view;
+ views[1 - future++] = m_VideoBuffers[i];
found = true;
break;
}
@@ -786,9 +841,10 @@ void CWinRenderer::RenderHW(DWORD flags)
bool found = false;
for (int i = 0; i < m_NumYV12Buffers; i++)
{
- if (buffers[i] && buffers[i]->pic && buffers[i]->frameIdx == image->frameIdx - (past*2 + 2))
+ if (m_VideoBuffers[i] && m_VideoBuffers[i]->HasPic()
+ && m_VideoBuffers[i]->frameIdx == image->frameIdx - (past*2 + 2))
{
- views[3 + past++] = buffers[i]->pic->view;
+ views[3 + past++] = m_VideoBuffers[i];
found = true;
break;
}
@@ -886,7 +942,7 @@ bool CWinRenderer::RenderCapture(CRenderCapture* capture)
CRect saveSize = m_destRect;
saveRotatedCoords();//backup current m_rotatedDestCoords
- m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
+ m_destRect.SetRect(0, 0, static_cast<float>(capture->GetWidth()), static_cast<float>(capture->GetHeight()));
syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
ID3D11DepthStencilView* oldDepthView;
@@ -928,26 +984,17 @@ bool CWinRenderer::CreateYV12Texture(int index)
CSingleLock lock(g_graphicsContext);
DeleteYV12Texture(index);
- if (m_renderMethod == RENDER_DXVA)
- {
- m_VideoBuffers[index] = new DXVABuffer();
- }
- else
+ m_VideoBuffers[index] = new SWinVideoBuffer();
+ if (!m_VideoBuffers[index]->CreateBuffer(m_bufferFormat, m_sourceWidth, m_sourceHeight, m_renderMethod == RENDER_SW))
{
- YUVBuffer *buf = new YUVBuffer();
- if (!buf->Create(m_format, m_sourceWidth, m_sourceHeight, m_renderMethod == RENDER_PS))
- {
- CLog::Log(LOGERROR, __FUNCTION__" - Unable to create YV12 video texture %i", index);
- delete buf;
- return false;
- }
- m_VideoBuffers[index] = buf;
+ CLog::Log(LOGERROR, "%s: unable to create video buffer %i", __FUNCTION__, index);
+ SAFE_DELETE(m_VideoBuffers[index]);
+ return false;
}
-
m_VideoBuffers[index]->StartDecode();
m_VideoBuffers[index]->Clear();
- CLog::Log(LOGDEBUG, "created video buffer %i", index);
+ CLog::Log(LOGDEBUG, "%s: created video buffer %i", __FUNCTION__, index);
return true;
}
@@ -968,7 +1015,6 @@ bool CWinRenderer::Supports(ERENDERFEATURE feature)
feature == RENDERFEATURE_POSTPROCESS)
return true;
-
return false;
}
@@ -999,8 +1045,8 @@ bool CWinRenderer::Supports(ESCALINGMETHOD method)
|| method == VS_SCALINGMETHOD_LANCZOS3)
{
// if scaling is below level, avoid hq scaling
- float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100;
- float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100;
+ float scaleX = fabs((static_cast<float>(m_sourceWidth) - m_destRect.Width())/m_sourceWidth)*100;
+ float scaleY = fabs((static_cast<float>(m_sourceHeight) - m_destRect.Height())/m_sourceHeight)*100;
int minScale = CServiceBroker::GetSettings().GetInt(CSettings::SETTING_VIDEOPLAYER_HQSCALERS);
if (scaleX < minScale && scaleY < minScale)
return false;
@@ -1058,7 +1104,8 @@ CRenderInfo CWinRenderer::GetRenderInfo()
info.max_buffer_size = NUM_BUFFERS;
if (m_renderMethod == RENDER_DXVA && m_processor)
{
- info.optimal_buffer_size = m_processor->Size();
+ int buffers = m_processor->Size() + m_processor->PastRefs(); // extra buffers for past refs
+ info.optimal_buffer_size = std::min(NUM_BUFFERS, buffers);
if (m_format != AV_PIX_FMT_D3D11VA_VLD)
info.m_deintMethods.push_back(VS_INTERLACEMETHOD_DXVA_AUTO);
}
@@ -1073,7 +1120,7 @@ void CWinRenderer::ReleaseBuffer(int idx)
SAFE_RELEASE(m_VideoBuffers[idx]->videoBuffer);
if (m_renderMethod == RENDER_DXVA && m_VideoBuffers[idx])
- SAFE_RELEASE(reinterpret_cast<DXVABuffer*>(m_VideoBuffers[idx])->pic);
+ m_VideoBuffers[idx]->ReleaseHWPicture();
}
bool CWinRenderer::NeedBuffer(int idx)
@@ -1081,13 +1128,10 @@ bool CWinRenderer::NeedBuffer(int idx)
// check if processor wants to keep past frames
if (m_renderMethod == RENDER_DXVA && m_processor)
{
- DXVABuffer** buffers = reinterpret_cast<DXVABuffer**>(m_VideoBuffers);
-
int numPast = m_processor->PastRefs();
- if (buffers[idx] && buffers[idx]->pic &&
- (buffers[idx]->pictureFlags & DVP_FLAG_INTERLACED))
+ if (m_VideoBuffers[idx] && m_VideoBuffers[idx]->HasPic())
{
- if (buffers[idx]->frameIdx + numPast*2 >= buffers[m_iYV12RenderBuffer]->frameIdx)
+ if (m_VideoBuffers[idx]->frameIdx + numPast*2 >= m_VideoBuffers[m_iYV12RenderBuffer]->frameIdx)
return true;
}
}
@@ -1132,339 +1176,3 @@ bool CWinRenderer::LoadCLUT()
free(pCLUT);
return true;
}
-
-
-//============================================
-
-YUVBuffer::~YUVBuffer()
-{
- Release();
-}
-
-bool YUVBuffer::Create(AVPixelFormat format, unsigned int width, unsigned int height, bool dynamic)
-{
- m_format = format;
- m_width = width;
- m_height = height;
- m_mapType = dynamic ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE;
- // Create the buffers with D3D11_USAGE_DYNAMIC which can be used as shader resource for PS rendering
- // or D3D11_USAGE_STAGING which can be read and written for SW rendering
- D3D11_USAGE usage = dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_STAGING;
-
- switch(m_format)
- {
- case AV_PIX_FMT_YUV420P10:
- case AV_PIX_FMT_YUV420P16:
- {
- if ( !planes[PLANE_Y].texture.Create(m_width, m_height, 1, usage, DXGI_FORMAT_R16_UNORM)
- || !planes[PLANE_U].texture.Create(m_width >> 1, m_height >> 1, 1, usage, DXGI_FORMAT_R16_UNORM)
- || !planes[PLANE_V].texture.Create(m_width >> 1, m_height >> 1, 1, usage, DXGI_FORMAT_R16_UNORM))
- return false;
- m_activeplanes = 3;
- break;
- }
- case AV_PIX_FMT_YUV420P:
- {
- if ( !planes[PLANE_Y].texture.Create(m_width, m_height, 1, usage, DXGI_FORMAT_R8_UNORM)
- || !planes[PLANE_U].texture.Create(m_width >> 1, m_height >> 1, 1, usage, DXGI_FORMAT_R8_UNORM)
- || !planes[PLANE_V].texture.Create(m_width >> 1, m_height >> 1, 1, usage, DXGI_FORMAT_R8_UNORM))
- return false;
- m_activeplanes = 3;
- break;
- }
- case AV_PIX_FMT_D3D11VA_VLD:
- case AV_PIX_FMT_NV12:
- {
- DXGI_FORMAT uvFormat = DXGI_FORMAT_R8G8_UNORM;
- // FL 9.x doesn't support DXGI_FORMAT_R8G8_UNORM, so we have to use SNORM and correct values in shader
- if (!g_Windowing.IsFormatSupport(uvFormat, D3D11_FORMAT_SUPPORT_TEXTURE2D))
- uvFormat = DXGI_FORMAT_R8G8_SNORM;
- if ( !planes[PLANE_Y].texture.Create( m_width, m_height, 1, usage, DXGI_FORMAT_R8_UNORM)
- || !planes[PLANE_UV].texture.Create(m_width >> 1, m_height >> 1, 1, usage, uvFormat))
- return false;
- m_activeplanes = 2;
- break;
- }
- case AV_PIX_FMT_YUYV422:
- {
- if ( !planes[PLANE_Y].texture.Create(m_width >> 1, m_height, 1, usage, DXGI_FORMAT_B8G8R8A8_UNORM))
- return false;
- m_activeplanes = 1;
- break;
- }
- case AV_PIX_FMT_UYVY422:
- {
- if ( !planes[PLANE_Y].texture.Create(m_width >> 1, m_height, 1, usage, DXGI_FORMAT_B8G8R8A8_UNORM))
- return false;
- m_activeplanes = 1;
- break;
- }
- default:
- m_activeplanes = 0;
- return false;
- }
-
- return true;
-}
-
-void YUVBuffer::Release()
-{
- SAFE_RELEASE(m_staging);
- for(unsigned i = 0; i < m_activeplanes; i++)
- {
- // unlock before release
- if (m_locked && planes[i].texture.Get() && planes[i].rect.pData)
- planes[i].texture.UnlockRect(0);
-
- planes[i].texture.Release();
- memset(&planes[i].rect, 0, sizeof(planes[i].rect));
- }
-}
-
-void YUVBuffer::StartRender()
-{
- if (!m_locked)
- return;
-
- if (m_bPending)
- {
- PerformCopy();
- m_bPending = false;
- }
-
- m_locked = false;
-
- for (unsigned i = 0; i < m_activeplanes; i++)
- {
- if (planes[i].texture.Get() && planes[i].rect.pData)
- if (!planes[i].texture.UnlockRect(0))
- CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock texture %d", i);
- memset(&planes[i].rect, 0, sizeof(planes[i].rect));
- }
-}
-
-void YUVBuffer::StartDecode()
-{
- if (m_locked)
- return;
-
- m_locked = true;
- m_bPending = false;
-
- for(unsigned i = 0; i < m_activeplanes; i++)
- {
- if(planes[i].texture.Get()
- && planes[i].texture.LockRect(0, &planes[i].rect, m_mapType) == false)
- {
- memset(&planes[i].rect, 0, sizeof(planes[i].rect));
- CLog::Log(LOGERROR, __FUNCTION__" - failed to lock texture %d into memory", i);
- m_locked = false;
- }
- }
-}
-
-void YUVBuffer::Clear()
-{
- // Set Y to 0 and U,V to 128 (RGB 0,0,0) to avoid visual artifacts at the start of playback
-
- switch(m_format)
- {
- case AV_PIX_FMT_YUV420P16:
- {
- wmemset((wchar_t*)planes[PLANE_Y].rect.pData, 0, planes[PLANE_Y].rect.RowPitch * m_height / 2);
- wmemset((wchar_t*)planes[PLANE_U].rect.pData, 32768, planes[PLANE_U].rect.RowPitch * (m_height / 2) / 2);
- wmemset((wchar_t*)planes[PLANE_V].rect.pData, 32768, planes[PLANE_V].rect.RowPitch * (m_height / 2) / 2);
- break;
- }
- case AV_PIX_FMT_YUV420P10:
- {
- wmemset((wchar_t*)planes[PLANE_Y].rect.pData, 0, planes[PLANE_Y].rect.RowPitch * m_height / 2);
- wmemset((wchar_t*)planes[PLANE_U].rect.pData, 512, planes[PLANE_U].rect.RowPitch * (m_height / 2) / 2);
- wmemset((wchar_t*)planes[PLANE_V].rect.pData, 512, planes[PLANE_V].rect.RowPitch * (m_height / 2) / 2);
- break;
- }
- case AV_PIX_FMT_YUV420P:
- {
- memset(planes[PLANE_Y].rect.pData, 0, planes[PLANE_Y].rect.RowPitch * m_height);
- memset(planes[PLANE_U].rect.pData, 128, planes[PLANE_U].rect.RowPitch * (m_height / 2));
- memset(planes[PLANE_V].rect.pData, 128, planes[PLANE_V].rect.RowPitch * (m_height / 2));
- break;
- }
- case AV_PIX_FMT_D3D11VA_VLD:
- case AV_PIX_FMT_NV12:
- {
- memset(planes[PLANE_Y].rect.pData, 0, planes[PLANE_Y].rect.RowPitch * m_height);
- memset(planes[PLANE_UV].rect.pData, 128, planes[PLANE_U].rect.RowPitch * (m_height / 2));
- break;
- }
- // YUY2, UYVY: wmemset to set a 16bit pattern, byte-swapped because x86 is LE
- case AV_PIX_FMT_YUYV422:
- {
- wmemset((wchar_t*)planes[PLANE_Y].rect.pData, 0x8000, planes[PLANE_Y].rect.RowPitch / 2 * m_height);
- break;
- }
- case AV_PIX_FMT_UYVY422:
- {
- wmemset((wchar_t*)planes[PLANE_Y].rect.pData, 0x0080, planes[PLANE_Y].rect.RowPitch / 2 * m_height);
- break;
- }
-
- }
-}
-
-bool YUVBuffer::IsReadyToRender()
-{
- return !m_locked;
-}
-
-bool YUVBuffer::CopyFromPicture(const VideoPicture &picture)
-{
- AVPixelFormat format = picture.videoBuffer->GetFormat();
- if (format == AV_PIX_FMT_D3D11VA_VLD)
- {
- DXVA::CDXVAVideoBuffer *hwpic = static_cast<DXVA::CDXVAVideoBuffer*>(picture.videoBuffer);
- return CopyFromDXVA(reinterpret_cast<ID3D11VideoDecoderOutputView*>(hwpic->picture->view));
- }
-
- if ( format == AV_PIX_FMT_YUV420P
- || format == AV_PIX_FMT_YUV420P10
- || format == AV_PIX_FMT_YUV420P16
- || format == AV_PIX_FMT_NV12)
- {
- uint8_t* bufData[3];
- int srcLines[3];
- picture.videoBuffer->GetPlanes(bufData);
- picture.videoBuffer->GetStrides(srcLines);
- std::vector<Concurrency::task<void>> tasks;
-
- for(unsigned plane = 0; plane < m_activeplanes; ++plane)
- {
- uint8_t* dst = static_cast<uint8_t*>(planes[plane].rect.pData);
- uint8_t* src = bufData[plane];
- int srcLine = srcLines[plane];
- int dstLine = planes[plane].rect.RowPitch;
- int height = plane == 0 ? picture.iHeight : picture.iHeight >> 1;
-
- auto task = Concurrency::create_task([src, dst, srcLine, dstLine, height]()
- {
- if (srcLine == dstLine)
- {
- memcpy(dst, src, srcLine * height);
- }
- else
- {
- uint8_t* s = src;
- uint8_t* d = dst;
- for(unsigned i = 0; i < height; ++i)
- {
- memcpy(d, s, std::min(srcLine, dstLine));
- d += dstLine;
- s += srcLine;
- }
- }
- });
- tasks.push_back(task);
- }
-
- when_all(tasks.begin(), tasks.end()).wait();//.then([this]() { StartRender(); });
- return true;
- }
- return false;
-}
-
-bool YUVBuffer::CopyFromDXVA(ID3D11VideoDecoderOutputView* pView)
-{
- if (!pView)
- return false;
-
- HRESULT hr = S_OK;
- D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC vpivd;
- pView->GetDesc(&vpivd);
- ID3D11Resource* resource = nullptr;
- pView->GetResource(&resource);
-
- if (!m_staging)
- {
- // create staging texture
- ID3D11Texture2D* surface = nullptr;
- hr = resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&surface));
- if (SUCCEEDED(hr))
- {
- D3D11_TEXTURE2D_DESC tDesc;
- surface->GetDesc(&tDesc);
- SAFE_RELEASE(surface);
-
- CD3D11_TEXTURE2D_DESC sDesc(tDesc);
- sDesc.ArraySize = 1;
- sDesc.Usage = D3D11_USAGE_STAGING;
- sDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- sDesc.BindFlags = 0;
-
- hr = g_Windowing.Get3D11Device()->CreateTexture2D(&sDesc, nullptr, &m_staging);
- if (SUCCEEDED(hr))
- m_sDesc = sDesc;
- }
- }
-
- if (m_staging)
- {
- ID3D11DeviceContext* pContext = g_Windowing.GetImmediateContext();
- // copy content from decoder texture to temporary texture.
- pContext->CopySubresourceRegion(m_staging,
- D3D11CalcSubresource(0, 0, 1),
- 0, 0, 0,
- resource,
- D3D11CalcSubresource(0, vpivd.Texture2D.ArraySlice, 1),
- nullptr);
- m_bPending = true;
- }
- SAFE_RELEASE(resource);
-
- return SUCCEEDED(hr);
-}
-
-void YUVBuffer::PerformCopy()
-{
- if (!m_locked)
- return;
-
- ID3D11DeviceContext* pContext = g_Windowing.GetImmediateContext();
- D3D11_MAPPED_SUBRESOURCE rectangle;
- if (SUCCEEDED(pContext->Map(m_staging, 0, D3D11_MAP_READ, 0, &rectangle)))
- {
- void* (*copy_func)(void* d, const void* s, size_t size) =
- ((g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_SSE4) != 0) ? gpu_memcpy : memcpy;
-
- uint8_t* s_y = static_cast<uint8_t*>(rectangle.pData);
- uint8_t *s_uv = static_cast<uint8_t*>(rectangle.pData) + m_sDesc.Height * rectangle.RowPitch;
- uint8_t* d_y = static_cast<uint8_t*>(planes[PLANE_Y].rect.pData);
- uint8_t *d_uv = static_cast<uint8_t*>(planes[PLANE_UV].rect.pData);
-
- if ( planes[PLANE_Y ].rect.RowPitch == rectangle.RowPitch
- && planes[PLANE_UV].rect.RowPitch == rectangle.RowPitch)
- {
- copy_func(d_y, s_y, rectangle.RowPitch * m_height);
- copy_func(d_uv, s_uv, rectangle.RowPitch * m_height >> 1);
- }
- else
- {
- for (unsigned y = 0; y < m_sDesc.Height >> 1; ++y)
- {
- // Copy Y
- copy_func(d_y, s_y, planes[PLANE_Y].rect.RowPitch);
- s_y += rectangle.RowPitch;
- d_y += planes[PLANE_Y].rect.RowPitch;
- // Copy Y
- copy_func(d_y, s_y, planes[PLANE_Y].rect.RowPitch);
- s_y += rectangle.RowPitch;
- d_y += planes[PLANE_Y].rect.RowPitch;
- // Copy UV
- copy_func(d_uv, s_uv, planes[PLANE_UV].rect.RowPitch);
- s_uv += rectangle.RowPitch;
- d_uv += planes[PLANE_UV].rect.RowPitch;
- }
- }
- pContext->Unmap(m_staging, 0);
- }
-}
-
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
index 8999a6b893..8c10a508c7 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
@@ -25,6 +25,7 @@
#include "HwDecRender/DXVAHD.h"
#include "guilib/D3DResource.h"
#include "RenderCapture.h"
+#include "WinVideoBuffer.h"
#include "settings/Settings.h"
#define ALIGN(value, alignment) (((value)+((alignment)-1))&~((alignment)-1))
@@ -77,80 +78,12 @@ enum RenderMethod
#define PLANE_U 1
#define PLANE_V 2
#define PLANE_UV 1
+#define PLANE_DXVA 0
#define FIELD_FULL 0
#define FIELD_TOP 1
#define FIELD_BOT 2
-struct SVideoBuffer
-{
- SVideoBuffer() : videoBuffer(nullptr) {}
- virtual ~SVideoBuffer() {}
- virtual void Release() {}; // Release any allocated resource
- virtual void StartDecode() {}; // Prepare the buffer to receive data from VideoPlayer
- virtual void StartRender() {}; // VideoPlayer finished filling the buffer with data
- virtual void Clear() {}; // clear the buffer with solid black
- virtual bool IsReadyToRender() { return true; };
-
- CVideoBuffer* videoBuffer = nullptr;
-};
-
-// YV12 decoder textures
-struct SVideoPlane
-{
- CD3DTexture texture;
- D3D11_MAPPED_SUBRESOURCE rect; // rect.pBits != NULL is used to know if the texture is locked
-};
-
-struct YUVBuffer : SVideoBuffer
-{
- YUVBuffer() : m_width(0), m_height(0)
- , m_format(AV_PIX_FMT_NONE)
- , m_activeplanes(0)
- , m_locked(false)
- , m_staging(nullptr)
- , m_bPending(false)
- {
- memset(&m_sDesc, 0, sizeof(CD3D11_TEXTURE2D_DESC));
- }
- ~YUVBuffer();
- bool Create(AVPixelFormat format, unsigned int width, unsigned int height, bool dynamic);
- unsigned int GetActivePlanes() { return m_activeplanes; }
- bool CopyFromPicture(const VideoPicture &picture);
-
- // SVideoBuffer overrides
- void Release() override;
- void StartDecode() override;
- void StartRender() override;
- void Clear() override;
- bool IsReadyToRender() override;
-
- SVideoPlane planes[3];
-
-private:
- bool CopyFromDXVA(ID3D11VideoDecoderOutputView* pView);
- void PerformCopy();
-
- unsigned int m_width;
- unsigned int m_height;
- AVPixelFormat m_format;
- unsigned int m_activeplanes;
- bool m_locked;
- D3D11_MAP m_mapType;
- ID3D11Texture2D* m_staging;
- CD3D11_TEXTURE2D_DESC m_sDesc;
- bool m_bPending;
-};
-
-struct DXVABuffer : SVideoBuffer
-{
- DXVABuffer() { pic = nullptr; }
- ~DXVABuffer() { SAFE_RELEASE(pic); }
- DXVA::CRenderPicture *pic;
- unsigned int frameIdx;
- unsigned int pictureFlags;
-};
-
class CWinRenderer : public CBaseRenderer
{
public:
@@ -197,7 +130,7 @@ protected:
void ManageTextures();
void DeleteYV12Texture(int index);
bool CreateYV12Texture(int index);
- int NextYV12Texture();
+ int NextYV12Texture() const;
void SelectRenderMethod();
void UpdateVideoFilter();
void SelectSWVideoFilter();
@@ -205,46 +138,45 @@ protected:
void UpdatePSVideoFilter();
void ColorManagmentUpdate();
bool CreateIntermediateRenderTarget(unsigned int width, unsigned int height, bool dynamic);
+ EBufferFormat SelectBufferFormat(const ERenderFormat format, const RenderMethod method) const;
bool LoadCLUT();
- int m_iYV12RenderBuffer;
- int m_NumYV12Buffers;
-
- bool m_bConfigured;
- SVideoBuffer *m_VideoBuffers[NUM_BUFFERS];
- RenderMethod m_renderMethod;
- DXVA::CProcessorHD *m_processor;
-
- // software scale libraries (fallback if required pixel shaders version is not available)
- struct SwsContext *m_sw_scale_ctx;
+ bool m_bConfigured;
bool m_bUseHQScaler;
- CD3DTexture m_IntermediateTarget;
- CYUV2RGBShader* m_colorShader;
- CConvolutionShader* m_scalerShader;
- COutputShader* m_outputShader;
+ bool m_bFilterInitialized;
+ bool m_cmsOn{ false };
+ bool m_useDithering;
- ESCALINGMETHOD m_scalingMethod;
- ESCALINGMETHOD m_scalingMethodGui;
+ unsigned int m_destWidth;
+ unsigned int m_destHeight;
+ unsigned int m_frameIdx;
- bool m_bFilterInitialized;
+ int m_iYV12RenderBuffer;
+ int m_NumYV12Buffers;
+ int m_neededBuffers;
int m_iRequestedMethod;
- DXGI_FORMAT m_dxva_format;
+ int m_cmsToken{ -1 };
+ int m_CLUTSize{ 0 };
+ int m_ditherDepth;
- // Width and height of the render target
- // the separable HQ scalers need this info, but could the m_destRect be used instead?
- unsigned int m_destWidth;
- unsigned int m_destHeight;
+ DXGI_FORMAT m_dxva_format;
+ RenderMethod m_renderMethod;
+ EBufferFormat m_bufferFormat;
+ ESCALINGMETHOD m_scalingMethod;
+ ESCALINGMETHOD m_scalingMethodGui;
- int m_neededBuffers;
- unsigned int m_frameIdx = 0;
- CRenderCapture* m_capture = nullptr;
+ std::vector<ERenderFormat> m_formats;
- int m_cmsToken{ -1 };
- bool m_cmsOn{ false };
- int m_CLUTSize{ 0 };
+ SWinVideoBuffer *m_VideoBuffers[NUM_BUFFERS];
+ DXVA::CProcessorHD *m_processor;
+ struct SwsContext *m_sw_scale_ctx;
+ CYUV2RGBShader* m_colorShader;
+ CConvolutionShader* m_scalerShader;
+ COutputShader* m_outputShader;
+ CRenderCapture* m_capture = nullptr;
std::unique_ptr<CColorManager> m_colorManager;
ID3D11ShaderResourceView *m_pCLUTView{ nullptr };
- bool m_useDithering;
- int m_ditherDepth;
+
+ CD3DTexture m_IntermediateTarget;
};