From 06501bd4b7b1b9f4e684ee78221d4a0a1e1d45db Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 18 Jul 2018 19:10:14 -0700 Subject: [PATCH] Fix video scaling on DXVA2 --- .../video/ffmpeg-renderers/dxva2.cpp | 49 ++++++++++++++----- app/streaming/video/ffmpeg-renderers/dxva2.h | 7 ++- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/dxva2.cpp b/app/streaming/video/ffmpeg-renderers/dxva2.cpp index 22ea6871..1da83e03 100644 --- a/app/streaming/video/ffmpeg-renderers/dxva2.cpp +++ b/app/streaming/video/ffmpeg-renderers/dxva2.cpp @@ -101,8 +101,8 @@ int DXVA2Renderer::ffGetBuffer2(AVCodecContext* context, AVFrame* frame, int) frame->data[3] = frame->buf[0]->data; frame->format = AV_PIX_FMT_DXVA2_VLD; - frame->width = me->m_Width; - frame->height = me->m_Height; + frame->width = me->m_VideoWidth; + frame->height = me->m_VideoHeight; return 0; } @@ -218,8 +218,8 @@ bool DXVA2Renderer::initializeDecoder() alignment = 16; } - hr = m_DecService->CreateSurface(FFALIGN(m_Width, alignment), - FFALIGN(m_Height, alignment), + hr = m_DecService->CreateSurface(FFALIGN(m_VideoWidth, alignment), + FFALIGN(m_VideoHeight, alignment), ARRAYSIZE(m_DecSurfaces) - 1, m_Desc.Format, D3DPOOL_DEFAULT, @@ -262,6 +262,9 @@ bool DXVA2Renderer::initializeRenderer() D3DSURFACE_DESC renderTargetDesc; m_RenderTarget->GetDesc(&renderTargetDesc); + m_DisplayWidth = renderTargetDesc.Width; + m_DisplayHeight = renderTargetDesc.Height; + hr = DXVA2CreateVideoService(m_Device, IID_IDirectXVideoProcessorService, reinterpret_cast(&m_ProcService)); @@ -302,6 +305,14 @@ bool DXVA2Renderer::initializeRenderer() caps.VideoProcessorOperations); continue; } + else if (!(caps.VideoProcessorOperations & DXVA2_VideoProcess_StretchX) || + !(caps.VideoProcessorOperations & DXVA2_VideoProcess_StretchY)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Device %d can't stretch video: %x", + i, + caps.VideoProcessorOperations); + continue; + } m_ProcService->GetProcAmpRange(guids[i], &m_Desc, renderTargetDesc.Format, DXVA2_ProcAmp_Brightness, &m_BrightnessRange); m_ProcService->GetProcAmpRange(guids[i], &m_Desc, renderTargetDesc.Format, DXVA2_ProcAmp_Contrast, &m_ContrastRange); @@ -341,8 +352,8 @@ bool DXVA2Renderer::initializeRenderer() bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, int height) { m_VideoFormat = videoFormat; - m_Width = width; - m_Height = height; + m_VideoWidth = width; + m_VideoHeight = height; // FFmpeg will be decoding on different threads than the main thread that we're // currently running on right now. We must set this hint so SDL will pass @@ -366,8 +377,8 @@ bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, i m_Device = SDL_RenderGetD3D9Device(m_SdlRenderer); RtlZeroMemory(&m_Desc, sizeof(m_Desc)); - m_Desc.SampleWidth = m_Width; - m_Desc.SampleHeight = m_Height; + m_Desc.SampleWidth = m_VideoWidth; + m_Desc.SampleHeight = m_VideoHeight; m_Desc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_ProgressiveChroma; m_Desc.SampleFormat.NominalRange = DXVA2_NominalRange_0_255; m_Desc.SampleFormat.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709; @@ -421,15 +432,31 @@ void DXVA2Renderer::renderFrame(AVFrame* frame) sample.SrcSurface = surface; sample.SrcRect.right = m_Desc.SampleWidth; sample.SrcRect.bottom = m_Desc.SampleHeight; - sample.DstRect = sample.SrcRect; sample.SampleFormat = m_Desc.SampleFormat; sample.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha(); + // Center in frame and preserve aspect ratio + double srcAspectRatio = (double)m_Desc.SampleWidth / (double)m_Desc.SampleHeight; + double dstAspectRatio = (double)m_DisplayWidth / (double)m_DisplayHeight; + if (dstAspectRatio < srcAspectRatio) { + // Greater height per width + int drawHeight = (int)(m_DisplayWidth / srcAspectRatio); + sample.DstRect.top = (m_DisplayHeight - drawHeight) / 2; + sample.DstRect.bottom = sample.DstRect.bottom + drawHeight; + sample.DstRect.right = m_DisplayWidth; + } + else { + // Greater width per height + int drawWidth = (int)(m_DisplayHeight * srcAspectRatio); + sample.DstRect.bottom = m_DisplayHeight; + sample.DstRect.left = (m_DisplayWidth - drawWidth) / 2; + sample.DstRect.right = drawWidth; + } + DXVA2_VideoProcessBltParams bltParams = {}; bltParams.TargetFrame = m_FrameIndex++; - bltParams.TargetRect.right = m_Desc.SampleWidth; - bltParams.TargetRect.bottom = m_Desc.SampleHeight; + bltParams.TargetRect = sample.DstRect; bltParams.BackgroundColor.Y = 0x1000; bltParams.BackgroundColor.Cb = 0x8000; bltParams.BackgroundColor.Cr = 0x8000; diff --git a/app/streaming/video/ffmpeg-renderers/dxva2.h b/app/streaming/video/ffmpeg-renderers/dxva2.h index f9589bef..c09c3b73 100644 --- a/app/streaming/video/ffmpeg-renderers/dxva2.h +++ b/app/streaming/video/ffmpeg-renderers/dxva2.h @@ -39,8 +39,11 @@ private: const enum AVPixelFormat* pixFmts); int m_VideoFormat; - int m_Width; - int m_Height; + int m_VideoWidth; + int m_VideoHeight; + + int m_DisplayWidth; + int m_DisplayHeight; SDL_Renderer* m_SdlRenderer;