VOID CD3DUtils::FillDefaultBltInfo(DXVA2_VideoProcessBltParams &blt) { blt.BackgroundColor.Alpha = 0xFFFF; blt.BackgroundColor.Y = 0; blt.BackgroundColor.Cr = 128; blt.BackgroundColor.Cb = 128; FillDefaultDXVAFormat(blt.DestFormat, DXVA2_SampleProgressiveFrame); blt.ProcAmpValues.Brightness = m_ProcAmpValues[0]; blt.ProcAmpValues.Contrast = m_ProcAmpValues[1]; blt.ProcAmpValues.Hue = m_ProcAmpValues[2]; blt.ProcAmpValues.Saturation = m_ProcAmpValues[3]; blt.Alpha = DXVA2_Fixed32OpaqueAlpha(); // DXVA2_VideoProcess_NoiseFilter blt.NoiseFilterLuma.Level = m_NFilterValues[0]; blt.NoiseFilterLuma.Threshold = m_NFilterValues[1]; blt.NoiseFilterLuma.Radius = m_NFilterValues[2]; blt.NoiseFilterChroma.Level = m_NFilterValues[3]; blt.NoiseFilterChroma.Threshold = m_NFilterValues[4]; blt.NoiseFilterChroma.Radius = m_NFilterValues[5]; // DXVA2_VideoProcess_DetailFilter blt.DetailFilterLuma.Level = m_DFilterValues[0]; blt.DetailFilterLuma.Threshold = m_DFilterValues[1]; blt.DetailFilterLuma.Radius = m_DFilterValues[2]; blt.DetailFilterChroma.Level = m_DFilterValues[3]; blt.DetailFilterChroma.Threshold = m_DFilterValues[4]; blt.DetailFilterChroma.Radius = m_DFilterValues[5]; }
static void FillBlitParams( DXVA2_VideoProcessBltParams *params, const RECT *area, const DXVA2_VideoSample *samples, int order ) { memset(params, 0, sizeof(*params)); params->TargetFrame = (samples->End - samples->Start) * order / 2; params->TargetRect = *area; params->DestData = 0; params->Alpha = DXVA2_Fixed32OpaqueAlpha(); params->DestFormat.SampleFormat = DXVA2_SampleProgressiveFrame; params->BackgroundColor.Alpha = 0xFFFF; params->ConstrictionSize.cx = params->TargetRect.right; params->ConstrictionSize.cy = params->TargetRect.bottom; }
HRESULT CD3DUtils::ProgressiveBlt(IDirect3DSurface9 *pSurfIn, IDirect3DSurface9 *pSurfOut) { if (!m_pVPDevice || !pSurfIn || !pSurfOut) return E_FAIL; DXVA2_VideoProcessBltParams blt = {0}; DXVA2_VideoSample samples[2] = {0}; RECT SrcRect = {0}; RECT DstRect = {0}; D3DSURFACE_DESC SrcDesc, DstDesc; IDirect3DSurface9 *pSrc = pSurfIn; IDirect3DSurface9 *pDst = pSurfOut; REFERENCE_TIME rtStart = 0; REFERENCE_TIME rtStop = 1; pSrc->GetDesc(&SrcDesc); pDst->GetDesc(&DstDesc); SrcRect.right = SrcDesc.Width; SrcRect.bottom = SrcDesc.Height; DstRect.right = DstDesc.Width; DstRect.bottom = DstDesc.Height; FillDefaultBltInfo(blt); blt.TargetFrame = rtStart; blt.TargetRect = DstRect; // DXVA2_VideoProcess_Constriction blt.ConstrictionSize.cx = blt.TargetRect.right - blt.TargetRect.left; blt.ConstrictionSize.cy = blt.TargetRect.bottom - blt.TargetRect.top; // // Initialize main stream video sample. // samples[0].Start = rtStart; samples[0].End = rtStop; FillDefaultDXVAFormat(samples[0].SampleFormat, DXVA2_SampleProgressiveFrame); samples[0].SrcSurface = pSrc; samples[0].SrcRect = SrcRect; samples[0].DstRect = DstRect; samples[0].PlanarAlpha = DXVA2_Fixed32OpaqueAlpha(); HRESULT hr = m_pVPDevice->VideoProcessBlt(pDst, &blt, samples, 1, NULL); return hr; }
static void FillSample( DXVA2_VideoSample *p_sample, const struct deinterlace_ctx *p_context, picture_t *p_pic, const video_format_t *p_fmt, const RECT *p_area, int i_field ) { picture_sys_t *p_sys_src = ActivePictureSys(p_pic); p_sample->SrcSurface = p_sys_src->surface; p_sample->SampleFormat.SampleFormat = p_pic->b_top_field_first ? DXVA2_SampleFieldInterleavedEvenFirst : DXVA2_SampleFieldInterleavedOddFirst; p_sample->Start = 0; p_sample->End = GetFieldDuration(p_context, p_fmt, p_pic) * 10; p_sample->SampleData = DXVA2_SampleData_RFF_TFF_Present; if (!i_field) p_sample->SampleData |= DXVA2_SampleData_TFF; else p_sample->SampleData |= DXVA2_SampleData_RFF; p_sample->DstRect = p_sample->SrcRect = *p_area; p_sample->PlanarAlpha = DXVA2_Fixed32OpaqueAlpha(); }
CDeinterlacer::FrameStatus CDeinterlacer_DXVA::GetFrame( CFrameBuffer *pDstBuffer, const CFrameBuffer *pSrcBuffer, bool fTopField, int Field) { const int Width = pDstBuffer->m_Width, Height = pDstBuffer->m_Height; if (!m_pVideoProcessor || m_Width != Width || m_Height != Height) { if (m_fOpenFailed) return FRAME_SKIP; if (!Open(Width, Height)) return FRAME_SKIP; } const size_t TotalSamples = m_BackwardRefSamples + m_ForwardRefSamples + 1; if (m_RefSamples.size() == TotalSamples) m_RefSamples.pop_front(); IDirect3DSurface9 *pSurface = GetFreeSurface(); if (!pSurface) { TRACE(TEXT("Unable to find unused surface\n")); return FRAME_SKIP; } HRESULT hr; D3DSURFACE_DESC desc; hr = pSurface->GetDesc(&desc); if (FAILED(hr)) { TRACE(TEXT("Failed to get surface desc (%x)\n"), hr); return FRAME_SKIP; } D3DLOCKED_RECT rect; hr = pSurface->LockRect(&rect, nullptr, D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK); if (FAILED(hr)) { TRACE(TEXT("Failed to lock surface (%x)\n"), hr); return FRAME_SKIP; } PixelCopyI420ToNV12( Width, Height, (uint8_t*)rect.pBits, (uint8_t*)rect.pBits + desc.Height * rect.Pitch, rect.Pitch, pSrcBuffer->m_Buffer[0], pSrcBuffer->m_Buffer[1], pSrcBuffer->m_Buffer[2], pSrcBuffer->m_PitchY, pSrcBuffer->m_PitchC); pSurface->UnlockRect(); SampleInfo Sample; Sample.pSurface = pSurface; Sample.StartTime = pDstBuffer->m_rtStart; Sample.EndTime = pDstBuffer->m_rtStop; Sample.fTopFieldFirst = fTopField; m_RefSamples.push_back(Sample); if (m_RefSamples.size() <= m_ForwardRefSamples) return FRAME_SKIP; m_FrameNumber++; DXVA2_VideoSample Samples[MAX_DEINTERLACE_SURFACES]; RECT rc = {0, 0, Width, Height}; ZeroMemory(Samples, sizeof(Samples)); size_t BackwardSamples = 0; if (m_RefSamples.size() > m_ForwardRefSamples + 1) BackwardSamples = m_RefSamples.size() - (m_ForwardRefSamples + 1); for (size_t i = 0; i < m_RefSamples.size(); i++) { DXVA2_VideoSample &vs = Samples[i]; vs.Start = m_FrameNumber + i - BackwardSamples; vs.End = vs.Start + 1; vs.SampleFormat = m_VideoDesc.SampleFormat; vs.SampleFormat.SampleFormat = m_RefSamples[i].fTopFieldFirst ? DXVA2_SampleFieldInterleavedEvenFirst : DXVA2_SampleFieldInterleavedOddFirst; vs.SrcSurface = m_RefSamples[i].pSurface; vs.SrcRect = rc; vs.DstRect = rc; vs.PlanarAlpha = DXVA2_Fixed32OpaqueAlpha(); } DXVA2_VideoProcessBltParams blt = {}; blt.TargetFrame = m_FrameNumber; blt.TargetRect = rc; blt.BackgroundColor.Y = 0x1000; blt.BackgroundColor.Cb = 0x8000; blt.BackgroundColor.Cr = 0x8000; blt.BackgroundColor.Alpha = 0xffff; blt.DestFormat.SampleFormat = DXVA2_SampleProgressiveFrame; blt.DestFormat.NominalRange = m_VideoDesc.SampleFormat.NominalRange; blt.DestFormat.VideoTransferFunction = DXVA2_VideoTransFunc_sRGB; blt.ProcAmpValues.Brightness = m_ProcAmpBrightness.DefaultValue; blt.ProcAmpValues.Contrast = m_ProcAmpContrast.DefaultValue; blt.ProcAmpValues.Hue = m_ProcAmpHue.DefaultValue; blt.ProcAmpValues.Saturation = m_ProcAmpSaturation.DefaultValue; blt.Alpha = DXVA2_Fixed32OpaqueAlpha(); blt.NoiseFilterLuma = m_NoiseFilterLuma; blt.NoiseFilterChroma = m_NoiseFilterChroma; blt.DetailFilterLuma = m_DetailFilterLuma; blt.DetailFilterChroma = m_DetailFilterChroma; pSurface = m_Surfaces.front(); hr = m_pVideoProcessor->VideoProcessBlt(pSurface, &blt, Samples, (UINT)m_RefSamples.size(), nullptr); if (FAILED(hr)) { TRACE(TEXT("VideoProcessBlt() failed (%x)\n"), hr); return FRAME_SKIP; } if (pDstBuffer->m_pSurface) { D3DSURFACE_DESC descSrc, descDst; D3DLOCKED_RECT rectSrc, rectDst; hr = pSurface->GetDesc(&descSrc); if (FAILED(hr)) { TRACE(TEXT("Failed to get surface desc (%x)\n"), hr); return FRAME_SKIP; } hr = pDstBuffer->m_pSurface->GetDesc(&descDst); if (FAILED(hr)) { TRACE(TEXT("Failed to get surface desc (%x)\n"), hr); return FRAME_SKIP; } hr = pSurface->LockRect(&rectSrc, nullptr, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); if (FAILED(hr)) { TRACE(TEXT("Failed to lock surface (%x)\n"), hr); return FRAME_SKIP; } hr = pDstBuffer->m_pSurface->LockRect(&rectDst, nullptr, D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK); if (FAILED(hr)) { TRACE(TEXT("Failed to lock surface (%x)\n"), hr); pSurface->UnlockRect(); return FRAME_SKIP; } PixelCopyNV12ToNV12( Width, Height, (uint8_t*)rectDst.pBits, (uint8_t*)rectDst.pBits + descDst.Height * rectDst.Pitch, rectDst.Pitch, (const uint8_t*)rectSrc.pBits, (const uint8_t*)rectSrc.pBits + descSrc.Height * rectSrc.Pitch, rectSrc.Pitch); pDstBuffer->m_pSurface->UnlockRect(); pSurface->UnlockRect(); } else { hr = pSurface->GetDesc(&desc); if (FAILED(hr)) { TRACE(TEXT("Failed to get surface desc (%x)\n"), hr); return FRAME_SKIP; } hr = pSurface->LockRect(&rect, nullptr, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); if (FAILED(hr)) { TRACE(TEXT("Failed to lock surface (%x)\n"), hr); return FRAME_SKIP; } #if 0 PixelCopyNV12ToI420( Width, Height, pDstBuffer->m_Buffer[0], pDstBuffer->m_Buffer[1], pDstBuffer->m_Buffer[2], pDstBuffer->m_PitchY, pDstBuffer->m_PitchC, (const uint8_t*)rect.pBits, (const uint8_t*)rect.pBits + desc.Height * rect.Pitch, rect.Pitch); #else PixelCopyNV12ToNV12( Width, Height, pDstBuffer->m_Buffer[0], pDstBuffer->m_Buffer[1], pDstBuffer->m_PitchY, (const uint8_t*)rect.pBits, (const uint8_t*)rect.pBits + desc.Height * rect.Pitch, rect.Pitch); pDstBuffer->m_Subtype = MEDIASUBTYPE_NV12; #endif pSurface->UnlockRect(); } const SampleInfo *pSample = &m_RefSamples[m_RefSamples.size() - 1 - m_ForwardRefSamples]; pDstBuffer->m_rtStart = pSample->StartTime; pDstBuffer->m_rtStop = pSample->EndTime; return FRAME_OK; }