//------------------------------------------------------------------------------------------------- static void FillSurfaceDX9(AMFContext *context, AMFSurface *surface) { HRESULT hr = S_OK; // fill surface with something something useful. We fill with color and color rect D3DCOLOR color1 = D3DCOLOR_XYUV (128, 255, 128); D3DCOLOR color2 = D3DCOLOR_XYUV (128, 0, 128); // get native DX objects IDirect3DDevice9 *deviceDX9 = (IDirect3DDevice9 *)context->pVtbl->GetDX9Device(context, AMF_DX9); // no reference counting - do not Release() AMFPlane *plane = surface->pVtbl->GetPlaneAt(surface, 0); IDirect3DSurface9* surfaceDX9 = (IDirect3DSurface9*)plane->pVtbl->GetNative(plane); // no reference counting - do not Release() hr = deviceDX9->lpVtbl->ColorFill(deviceDX9, surfaceDX9, NULL, color1); if(xPos + rectSize > widthIn) { xPos = 0; } if(yPos + rectSize > heightIn) { yPos = 0; } RECT rect = {xPos, yPos, xPos + rectSize, yPos + rectSize}; hr = deviceDX9->lpVtbl->ColorFill(deviceDX9, surfaceDX9, &rect, color2); xPos+=2; //DX9 NV12 surfaces do not accept odd positions - do not use ++ yPos+=2; //DX9 NV12 surfaces do not accept odd positions - do not use ++ }
HRESULT CDXVA2Allocator::Alloc() { CAutoLock Lock(this); TRACE(TEXT("CDXVA2Allocator::Alloc()\n")); if (!m_pFilter->m_pD3DDeviceManager) return E_UNEXPECTED; HRESULT hr; IDirectXVideoDecoderService *pDecoderService; hr = m_pFilter->m_pD3DDeviceManager->GetVideoService( m_pFilter->m_hDXVADevice, IID_PPV_ARGS(&pDecoderService)); if (FAILED(hr)) { TRACE(TEXT("IDirect3DDeviceManager9::GetVideoService() failed (%x)\n"), hr); return hr; } hr = CBaseAllocator::Alloc(); /* if (hr == S_FALSE) { pDecoderDevice->Release(); return S_OK; } */ if (SUCCEEDED(hr)) { Free(); m_SurfaceList.resize(m_lCount); const int Width = m_pFilter->GetAlignedWidth(), Height = m_pFilter->GetAlignedHeight(); TRACE(TEXT("Create DXVA2 surfaces : %d x [%d x %d]\n"), m_lCount, Width, Height); hr = pDecoderService->CreateSurface( Width, Height, m_lCount - 1, D3DFMT_NV12, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, &m_SurfaceList[0], nullptr); if (FAILED(hr)) { TRACE(TEXT("IDirectXVideoDecoderService::CreateSurface() failed (%x)\n"), hr); m_SurfaceList.clear(); } else { IDirect3DDevice9 *pD3DDevice; hr = m_SurfaceList.front()->GetDevice(&pD3DDevice); if (FAILED(hr)) pD3DDevice = nullptr; for (int i = m_lCount - 1; i >= 0; i--) { IDirect3DSurface9 *pSurface = m_SurfaceList[i]; if (pD3DDevice) { pD3DDevice->ColorFill(pSurface, nullptr, D3DCOLOR_XYUV(16, 128, 128)); } CDXVA2MediaSample *pSample = DNew_nothrow CDXVA2MediaSample(this, &hr); if (!pSample) { hr = E_OUTOFMEMORY; break; } if (FAILED(hr)) { delete pSample; break; } pSample->SetSurface(i, pSurface); m_lFree.Add(pSample); } if (pD3DDevice) pD3DDevice->Release(); if (SUCCEEDED(hr)) { m_lAllocated = m_lCount; hr = m_pFilter->OnDXVA2SurfaceCreated(&m_SurfaceList[0], m_lAllocated); } else { Free(); } } } pDecoderService->Release(); if (SUCCEEDED(hr)) { m_bChanged = FALSE; } return hr; }
HRESULT CDecDXVA2::CreateDXVA2Decoder(int nSurfaces, IDirect3DSurface9 **ppSurfaces) { DbgLog((LOG_TRACE, 10, L"-> CDecDXVA2::CreateDXVA2Decoder")); HRESULT hr = S_OK; LPDIRECT3DSURFACE9 pSurfaces[DXVA2_MAX_SURFACES]; if (!m_pDXVADecoderService) return E_FAIL; DestroyDecoder(false, true); GUID input = GUID_NULL; D3DFORMAT output; FindVideoServiceConversion(m_pAVCtx->codec_id, &input, &output); if (!nSurfaces) { m_dwSurfaceWidth = GetAlignedDimension(m_pAVCtx->coded_width); m_dwSurfaceHeight = GetAlignedDimension(m_pAVCtx->coded_height); m_NumSurfaces = GetBufferCount(); hr = m_pDXVADecoderService->CreateSurface(m_dwSurfaceWidth, m_dwSurfaceHeight, m_NumSurfaces - 1, output, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, pSurfaces, nullptr); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Creation of surfaces failed with hr: %X", hr)); m_NumSurfaces = 0; return E_FAIL; } ppSurfaces = pSurfaces; } else { m_NumSurfaces = nSurfaces; for (int i = 0; i < m_NumSurfaces; i++) { ppSurfaces[i]->AddRef(); } } if (m_NumSurfaces <= 0) { DbgLog((LOG_TRACE, 10, L"-> No surfaces? No good!")); return E_FAIL; } // get the device, for ColorFill() to init the surfaces in black IDirect3DDevice9 *pDev = nullptr; ppSurfaces[0]->GetDevice(&pDev); for (int i = 0; i < m_NumSurfaces; i++) { m_pSurfaces[i].index = i; m_pSurfaces[i].d3d = ppSurfaces[i]; m_pSurfaces[i].age = 0; m_pSurfaces[i].used = false; // fill the surface in black, to avoid the "green screen" in case the first frame fails to decode. if (pDev) pDev->ColorFill(ppSurfaces[i], NULL, D3DCOLOR_XYUV(0, 128, 128)); } // and done with the device SafeRelease(&pDev); DbgLog((LOG_TRACE, 10, L"-> Successfully created %d surfaces (%dx%d)", m_NumSurfaces, m_dwSurfaceWidth, m_dwSurfaceHeight)); DXVA2_VideoDesc desc; ZeroMemory(&desc, sizeof(desc)); desc.SampleWidth = m_pAVCtx->coded_width; desc.SampleHeight = m_pAVCtx->coded_height; desc.Format = output; hr = FindDecoderConfiguration(input, &desc, &m_DXVAVideoDecoderConfig); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> FindDecoderConfiguration failed with hr: %X", hr)); return hr; } IDirectXVideoDecoder *decoder = nullptr; hr = m_pDXVADecoderService->CreateVideoDecoder(input, &desc, &m_DXVAVideoDecoderConfig, ppSurfaces, m_NumSurfaces, &decoder); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> CreateVideoDecoder failed with hr: %X", hr)); return E_FAIL; } m_pDecoder = decoder; m_guidDecoderDevice = input; /* fill hwaccel_context */ FillHWContext((dxva_context *)m_pAVCtx->hwaccel_context); memset(m_pRawSurface, 0, sizeof(m_pRawSurface)); for (int i = 0; i < m_NumSurfaces; i++) { m_pRawSurface[i] = m_pSurfaces[i].d3d; } return S_OK; }